0-1背包问题
- 设F[k][b]表示考虑前k个物品,总重量不超过b的情况下的可以装进背包的最大价值时多少?递推公式为:
- F[k][b] = max(F[k-1][b], F[k-1][b-weight[k]]+value[k]); b>=weight[k]
- F[k][b] = F[k-1][b];b<weight[k]
- 初始化时,二维矩阵所有值初始化为0,F[k][0] = 0, F[0][b] = 0;
如果对0-1背包进行空间优化,可以设置1维数组vector<int> F(B+1, 0);
此时递推公式变为: - F[b] = max(F[b], F[b-weight[k]]+value[k]); b>=weight[k]
- F[b] = F[b];b<weight[k]
- 初始化时,F中所有元素为0,在进行循环时,b需要从最大的B开始递减循环,因为当b>weight[k]时,F[k][b]的计算需要用到F[k-1][b-weight[k]]的结果,使用1维数组时,计算F[b]需要用到F[b-weight[k]],因此需要从高往低递减的迭代计算。
参考例题:http://bailian.openjudge.cn/practice/4131/
完全背包问题
- 完全背包时,每个物品数量不限,递推公式变为:
- F[k][b] = max(F[k-1][b], F[k][b-weight[k]]+value[k]); b>=weight[k]
- F[k][b] = F[k-1][b];b<weight[k]
如果对完全背包问题进行空间优化,可以设置1维数组vector<int> F(B+1, 0);
此时递推公式变为: - F[b] = max(F[b], F[b-weight[k]]+value[k]); b>=weight[k]
- F[b] = F[b];b<weight[k]
- 初始化时,F中所有元素为0,唯一和0-1背包不同的是,在进行循环时,b从0开始往B递增计算,因为计算F[k][b]时需要用到F[k][b-weight[k]],这就不是从高往低计算。
- 参考例题1:http://bailian.openjudge.cn/practice/2063/
- 参考例题2:http://bailian.openjudge.cn/practice/1787
0-1恰好装满问题
判断给定的重量B,K个物品是否能够恰好到B重量。假设F[k][b] = 0表示无法恰好装满,F[k][b]=1表示可以恰好装满。恰好装满的问题完全可以用0-1背包的问题来解决,但是唯一不同的是初始化的问题。
- 0-1背包问题中,F[k][0] = 0(0<=k<=K)。
- 在恰好装满问题中,F[k][0] = 1, 因为重量为0,一个物品都不装就可以恰好装满。
递推公式为:
- F[k][b] = max(F[k-1][b], F[k-1][b-weight[k]]+value[k]); b>=weight[k]
- F[k][b] = F[k-1][b];b<weight[k]
- 初始化时,数组中所有元素初始化为0,然后设设F[k][0] = 1,(0<=k<=K);
优化空间后,递推公式为:
- F[b] = max(F[b], F[b-weight[k]]); b>=weight[k]
- F[b] = F[b];b<weight[k]
- 初始化时,F[0] = 1,注意与0-1背包的区别。
0-1恰好装满时价值最小
参考习题:http://bailian.openjudge.cn/practice/1384/
K个背包,总重量不超过B的情况下,恰好装满背包时最小价值是多少。假设F[k][b]表示考虑前k个物品,重量不超过b时的最小价值。递推公式为:
- F[k][b] = min(F[k-1][b], F[k-1][b-weight[k]]+value[k]); b>=weight[k]
- F[k][b] = F[k-1][b];b<weight[k]
- 初始化时,首先将所有的元素设置为max_value, 可以定义为1e9,但是不要设置为INT_MAX, 但是令F[k][0] = 0,因为总重不超过0可以恰好装满,而且最小价值为0。
进行优化时,递推公式变为:
- F[b] = max(F[b], F[b-weight[k]]+value[k]); b>=weight[k]
- F[b] = F[b];b<weight[k]
- 初始化时,F中所有元素设置为max_value,但是F[0]设置为0,因为是0-1背包问题,b的循环必须是从高到低。
- 如果是完全背包问题,则b的循环是从低到高。