0-1背包
例六、 Charm Bracelet 0-1背包问题(POJ3624)
有N件物品和一个容积为M的背包。第i件物品的体积 w[i],价值是d[i]。求解将哪些物品装入背包可使价值总 和最大。每种物品只有一件,可以选择放或者不放 (N<=3500,M <= 13000)。
21
0-1背包问题(POJ3624)
用 F[i][j] 表示取前i种物品,使它们总体积不超过j的最优 取法取得的价值总和。要求F[N][M]
边界:if (w[1] <= j)
F[1][j] = d[1];
else
F[1][j] = 0;
22
0-1背包问题(POJ3624)
用 F[i][j] 表示取前i种物品,使它们总体积不超过j的最优 取法取得的价值总和
递推: F[i][j] = max(F[i-1][j],F[i-1][j-w[i]]+d[i])
取或不取第 i种物品,两者选优 (j-w[i] >= 0才有第二项)
23
0-1背包问题(POJ3624)
F[i][j] = max(F[i-1][j],F[i-1][j-w[i]]+d[i])
本题如用记忆型递归,需要一个很大的二维数组,会 超内存。注意到这个二维数组的下一行的值,只用到了 上一行的正上方及左边的值,因此可用滚动数组的思想 ,只要一行即可。即可以用一维数组,用“人人为我” 递推型动归实现。
递归:
#include <iostream> using namespace std; int W[10]; int D[10]; int F(int i,int j){ if(i==1&&W[1]<=j) return D[1]; else if(i==1)return 0; if(j-W[i]>=0) return max(F(i-1,j),F(i-1,j-W[i]) +D[i]);else{ return F(i-1,j); } } int main(){ for(int i=1;i<=3;i++) { cin>>W[i]; } for(int j=1;j<=3;j++) cin>>D[j]; cout<<F(3,40); }
递推:节省空间
#include <iostream> using namespace std; int w[10]; int n; int j; int d[10]; int F[100];//滚动数组 int main(){ cin>>n; cin>>j; for(int i=1;i<=n;i++){ cin>>w[i]; } for(int i=1;i<=n;i++){ cin>>d[i]; } for(int k=0;k<=j;k++) { if(w[1]<=k) F[k]=d[1]; else F[k]=0; } int temp=0; for(int i=2;i<=n;i++)//状态只用到正上方和左侧,所以从最右侧开始递推 { for(int k=j;k>=0;k--) { if(k>=w[i]) { temp=max(F[k],F[k-w[i]]+d[i]); F[k]=temp; } } cout<<F[j]; }
本文来自博客园,作者:坤k,转载请注明原文链接:https://www.cnblogs.com/fukunwang/p/15722405.html