2.3日学习总结

背包问题:

背包问题的解决过程

在解决问题之前,为描述方便,首先定义一些变量:Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积,定义V(i,j):当前背包容量 j,前 i 个物品最佳组合对应的价值,同时背包问题抽象化(X1,X2,…,Xn,其中 Xi 取0或1,表示第 i 个物品选或不选)。

1、建立模型,即求max(V1X1+V2X2+…+VnXn);

2、寻找约束条件,W1X1+W2X2+…+WnXn

3、寻找递推关系式,面对当前商品有两种可能性:

包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);

还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}。

其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i),但价值增加了v(i);

由此可以得出递推关系式:

j

j>=w(i) V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}

#include 
 
int main() {
 
    // 定义数组a用于存储每个节点的权值,数组b作为邻接矩阵存储节点间的连接关系
 
    // dp数组用于存储从每个节点出发能得到的最大权值和,d数组用于记录路径
 
    int a[30], b[30][30] = {0}, n, dp[30] = {0}, d[30] = {0};
 
    // 读取节点的数量n
 
    scanf("%d", &n);
 
    // 读取每个节点的权值,存储到数组a中,这里从a[1]到a[n]存储有效数据
 
    for (int i = 1; i <= n; i++)
 
        scanf("%d", &a[i]);
 
    // 读取邻接矩阵b的上三角部分,表示节点之间的连接关系
 
    // b[i][j]为1表示节点i到节点j有一条边
 
    for (int i = 1; i < n; i++) {
 
        for (int j = i + 1; j <= n; j++) {
 
            scanf("%d", &b[i][j]);
 
        }
 
    }
 
    // 初始化dp[n]为节点n的权值,因为从节点n出发没有后续节点,所以它的最大权值和就是自身权值
 
    dp[n] = a[n];
 
    // 记录当前最大权值和对应的节点编号,初始化为n
 
    int maxi = n;
 
    // 从倒数第二个节点开始向前遍历,计算从每个节点出发的最大权值和
 
    for (int i = n - 1; i >= 1; i--) {
 
        // 初始化dp[i]为节点i的权值
 
        dp[i] = a[i];
 
        // 初始化d[i]为0,表示当前还没有找到后续能使权值和更大的节点
 
        d[i] = 0;
 
        // 遍历节点i之后的所有节点j,寻找从节点i到节点j的路径
 
        for (int j = i + 1; j <= n; j++) {
 
            // 如果节点i到节点j有边,并且通过节点j能使从节点i出发的权值和更大
 
            if (b[i][j] == 1 && dp[j] + a[i] > dp[i]) {
 
                // 更新从节点i出发的最大权值和
 
                dp[i] = dp[j] + a[i];
 
                // 记录使权值和最大的后续节点j
 
                d[i] = j;
 
            }
 
        }
 
        // 如果当前节点i的最大权值和大于之前记录的最大权值和
 
        if (dp[i] > dp[maxi])
 
            // 更新最大权值和对应的节点编号为i
 
            maxi = i;
    }
 
    // 从最大权值和对应的节点maxi开始,按照记录的路径输出路径上的节点
 
    int t = maxi;
 
    while (t > 0) {
 
        printf("%d ", t);
 
        t = d[t];
    }
 
    printf("\n");
 
    // 输出从最大权值和对应的节点出发能得到的最大权值和
 
    printf("%d", dp[maxi]);
 
    return 0;
 
}
 
#include
 
// 定义一个函数max,用于返回两个整数中的较大值
 
int max(int a, int b) {
 
    return a > b? a : b;
 
}
 
int main() {
 
    // t表示背包的容量,m表示物品的数量
 
    // w数组用于存储每个物品的重量,v数组用于存储每个物品的价值
 
    // dp数组是动态规划的核心数组,dp[i][j]表示考虑前i个物品,背包容量为j时能获得的最大价值
 
    int t, m, w[103], v[103], dp[103][1003];
 
    // 读取背包的容量t和物品的数量m
 
    scanf("%d %d", &t, &m);
 
    // 依次读取每个物品的重量和价值,并存储到w数组和v数组中
 
    for (int i = 1; i <= m; i++) {
 
        scanf("%d %d", &w[i], &v[i]);
 
    }
 
    // 动态规划核心部分,通过两层循环填充dp数组
 
    // 外层循环遍历每个物品,从第1个物品到第m个物品
 
    for (int i = 1; i <= m; i++) {
 
        // 内层循环从背包容量t开始递减到0,用于计算在不同背包容量下的最大价值
 
        for (int j = t; j >= 0; j--) {
 
            // 如果当前背包容量j大于等于当前物品i的重量w[i],说明可以放入该物品
 
            if (j >= w[i]) {
 
                // 此时有两种选择:放入物品i,价值为dp[i - 1][j - w[i]] + v[i];不放入物品i,价值为dp[i - 1][j]
 
                // 取两者中的较大值作为dp[i][j]的值
 
                dp[i][j] = max(dp[i - 1][j - w[i]] + v[i], dp[i - 1][j]);
 
            } else {
 
                // 如果当前背包容量j小于当前物品i的重量w[i],则无法放入该物品
 
                // 此时dp[i][j]的值等于不考虑当前物品i时,背包容量为j的最大价值,即dp[i - 1][j]
 
                dp[i][j] = dp[i - 1][j];
 
            }
 
        }
 
    }
 
    // 输出考虑所有m个物品,背包容量为t时能获得的最大价值
 
    printf("%d", dp[m][t]);
 
    return 0;
 
}

串:

定义:
串(string)是由零个或多个字符组成的有限序列,又称为字符串。一般记为s = 'a₀a₁a₂…aₙ₋₁',其中s是串的名字,用单引号括起来的字符序列是串的值,'aᵢ'(0≤i<n)可以是字母、数字或其他字符。例如,'hello world'就是一个串。
串的相关术语
空串:不含任何字符的串称为空串,记为""或∅,其长度为 0。
空格串:由一个或多个空格组成的串称为空格串,它的长度为空格的个数。 例如,' '是长度为 3 的空格串,要注意空格串与空串是不同的。
子串与主串:串中任意个连续的字符组成的子序列称为该串的子串,包含子串的串相应地称为主串。例如,在串'abcdef'中,'bcd'是它的一个子串,而'abcdef'就是主串。子串在主串中的位置是指子串的第一个字符在主串中的序号,通常主串中字符的序号从 0 开始计数。例如,子串'bcd'在主串'abcdef'中的位置是 1。
串相等:两个串相等当且仅当它们的长度相等且对应位置的字符都相同。例如,'abc'和'abc'相等,而'abc'和'abd'不相等。

 串的顺序存储:

#define maxlen 255			//预定最大串长为255
typedef struct
{
	char ch[maxlen];		//每个分量存储一个字符
	int length;				//串的长度
}sstring;
 
typedef struct
{
	char *ch;				//按串长分配存储区,ch指向串的基地址
	int length;				//串的长度
}hstring;
int main()
{
	hstring s;
	s.ch = (char*)malloc(maxlen * sizeof(char));
	s.length = 0;
}

 简单总结:

今天是第二阶段学习的第一天,学习了串和深入了解了背包问题,明天将学习栈跟队列,并了解二叉树。

你可能感兴趣的:(学习)