动态规划
(参照刘汝佳代码)
1.
有n种物品,每种只有一个.第i种物品的体积是Vi , 重量为Wj , 选一些物品装到一个容量为C的背包,
使得背包里面的物品不超过总体积C的前提下重量尽可能的大.
1<=n<=100,
1<=Vi<=C<=10000,1<=Wi<=10^6
解法1:
状态方程: d(i,j) = max( d(i+1,j) , d(i+1,j-v[i]) +
w[j] ); (i > n 时,d(i,j) =
0.)
d(i,j)表示 当前第i层,背包剩余容量为j时接下来的最大重量和.
代码: d[1][c]为结果
for(int i = n; i >= 1;
--i)
{
for(int j = 0; j <= c;
++j)
{
d[i][j] = (i == n ? 0 : d[i+1][j]);
if(j >= v[i])
{
if(d[i][j] <=
d[i+1][j-v[i]]+w[i])
d[i][j] = d[i+1][j-v[i]]+w[i];
}
}
}
解法2: 相反的规划方向.
采用对称的状态. 设f(i,j)
表示把前i个物品装到容量为j的最大总重量.
状态方程: f(i,j) = max( f(i-1,j) ,
f(i-1,j-v[i])+w[i] );
i == 0 时为0 , j < 0时负无穷.
结果为f(n,c);
代码:
for(int i =1 ; i <= n;
++i)
{
for(int j = 0; j <= c;
++j)
{
f[i][j] = (i == 1 ? 0 : f[i-1][j]);
if(j >= v[i])
{
if(f[i][j] <=
f[i-1][j-v[i]]+w[i])
f[i][j] = f[i-1][j-v[i]]+w[i];
}
}
}
总结: 尽管在很多情况下,记忆化(剪枝)搜索程序直观,易懂. 但是计算顺序如果变得重要时
明显是递推时比较方便.效率相应高些. 同时规划的方向也是不唯一的看个人思维方向.