简单递推
【A题】
之前好像讲过,找到递推关系就可以啦
注意
动态规划问题,必须满足最优化定理(一个最优策略的所有子策略也是最优的)&&无后效性定理(未来与过去没有关系)
01背包
题目
每种物品只有一个,选还是不选
每件物品有不同的体积和价值(每种只有一件),给出一定的体积,求最大的价值
Ⅰ 递归解法
-
函数 K S ( i , j ) KS(i,j) KS(i,j):代表当前背包剩余容量为j时,前i个物品最佳组合所对应的价值
-
有以下两种可能
- 背包剩余容量不足以容纳该物品
此时背包的价值与前i-1个物品的价值是一样的, K S ( i , j ) = K S ( i − 1 , j ) KS(i,j) = KS(i-1,j) KS(i,j)=KS(i−1,j) - 背包剩余容量可以装下该商品,此时需要进行判断,因为装了该商品不一定能使最终组合达到最大价值
▶ 如果不装该商品,则价值为: K S ( i − 1 , j ) KS(i-1,j) KS(i−1,j)
▶ 如果装了该商品,则价值为 K S ( i − 1 , j − w i ) + v i KS(i-1,j-wi) + vi KS(i−1,j−wi)+vi, 从两者中选择较大的那个,所以就得出了递推关系式
- 背包剩余容量不足以容纳该物品
int ks(int i, int c) {
int result = 0;
if (i == 0 || c == 0)
{
// 初始条件
result = 0;
}
else if (ws[i] > c)
{
// 超出体积,依次退回
result = ks(i - 1, c);
}
else
{
// 可以放下
int tmp1 = ks(i - 1, c);
int tmp2 = ks(i - 1, c - ws[i]) + vs[i];
result = max(tmp1, tmp2);
}
return result;
}
}
Ⅱ 动态规划解法
用一个二维数组用来存储中间结果,减少重复计算
int ks3(int i, int j) {
// 初始化
for (int m = 0; m <= i; m++)
{
results[m][0] = 0;
}
for (int m = 0; m <= j; m++)
{
results[0][m] = 0;
}
// 开始填表
for (int m = 1; m <= i; m++)
{
for (int n = 1; n <= j; n++)
{
if (n < ws[m])
{
// 装不进去
results[m][n] = results[m - 1][n];
}
else
{
// 容量足够
if (results[m - 1][n] > results[m - 1][n - ws[m]] + vs[m])
{
//
results[m][n] = results[m - 1][n];
}
else
{
results[m][n] = results[m - 1][n - ws[m]] + vs[m];
}
}
}
}
return results[i][j];
}