标签:描述 递推 定义 i++ code 顺序 字典 scan i+1
1、多阶段决策问题
(1)物品无限的背包 问题
比较原来的硬币问题发现,只是增加了一个重量属性,从而由原来的无权图变成了带权图,这样问题就变成了求以C为起点(终点任意)的、边权之和最大的路径,相对的
d(s)=max(d(s-v[i])+1)变为d(s)=max(d(s-v[i])+w[i])。
(2)0-1背包问题
状态及其转移类似于回溯法中的解答树,解答树的层数,也就是递归函数中的当前填充位置cur,描述的是即将完成的决策序号,在动态规划中称为阶段。
设d(i,j)表示当前在第i层,背包剩余容量为j时接下来的最大重量和,d(i,j)=max{d(i+1,j),d(i+1,j-v[i])+w[i]},边界是i>n时,d=0。简单来说d(i,j)表示把第i,i+1,,,n个物品撞到容量为
j的背包中的最大总重量。
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]) 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]},最终答案f(n,C)
for(int i=1;i<=n;i++) for(int j=0;j<=C;j++) { f[i][j]=(i==0?0:f[i-1][j]); if(j>=v[i]) f[i][j] >?=f[i-1][j-v[i]]+w[i]; }
3、滚动数组
memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) { scanf("%d%d",&v,&w); for(int j=C;j>=0;j--) if(j>=v) f[j] >?=f[j-v]+w; }
在递推法中,如计算顺序很特殊,且计算新状态用到的原状态不多,可以尝试滚动数组。但是会让解的打印方案变得复杂。如要求字典序最小的打印方案,则慎用滚动数组,且规划方向也一般用后i个物品最大重量的规划方向。
标签:描述 递推 定义 i++ code 顺序 字典 scan i+1
原文地址:https://www.cnblogs.com/tuilinengshou/p/11618613.html