2019-11-30
10:05:54
如何把背包问题画一幅DAG呢?这是自己最近很困惑的。想看看到底这个DAG是啥样!
#include <bits/stdc++.h> #include <stdlib.h> #include <stdio.h> using namespace std; #define maxn 10005 #define M 105 int c[M][maxn]; int w[M],v[M]; int x[M];//x[M]表示第i个物品是否放入购物车 int main(){ int i,j,n,W; cout<<"请输入物品的个数: "; cin>> n; cout<<"请输入购物车的容量:"; cin>>W; cout<<"请输入每个物品的重量w 和 价值 v,用空格分开:"; for(int i=1;i<=n;++i){ cin>>w[i]>>v[i]; } for(i=0;i<=n;++i){ c[i][0]=0; } for(j=0;j<=W;++j){ c[0][j] = 0; } for(i=1;i<=n;++i){ for(int j=1;j<=W;++j){ if(j<w[i]){//当物品重量大于购物车容量时,不放入 c[i][j] = c[i-1][j]; } else{ c[i][j] = max(c[i-1][j],c[i-1][j-w[i]]+v[i]); } } } cout<<"装入购物车的最大价值为: "<<c[n][W]<<endl; //逆向构造最优解 j = W; for(i=n;i>0;--i){ if(c[i][j]>c[i-1][j]){ x[i]=1; j -= w[i]; }else{ x[i] = 0; } } cout<<"装入购物车的物品为:"<<endl; for(int i=1;i<=n;++i){ if(x[i]==1){ cout<<i<<" "; } } system("pause"); return 0; }
优化成一维数组:
逆序的关键是:如果是正序,则求f[v]时,f[0],...f[v-1]都已经改变过!里面存的不是i-1时刻的值。这样求f[v]时必定是错误的!
看一下错误的正序时的结果:
这是正确的逆序时的结果:
#include <bits/stdc++.h> #include <stdlib.h> #include <stdio.h> using namespace std; #define maxn 10005 #define M 105 int dp[maxn];//dp[i]表示当前已放入容量为j 的购物车获得的最大价值 int w[M],v[M]; int x[M];//x[i]表示第i个物品是否放入购物车 int i,j,n,W;//n表示n个物品,W表示购物车容量 void opt1(int n,int W){ for(int i=1;i<=n;++i){ for(j=W;j>0;--j){ if(j>=w[i]){ dp[j] = max(dp[j],dp[j-w[i]]+v[i]); } } } } int main(){ cout<<"请输入物品的个数: "; cin>>n; cout<<"请输入购物车的容量: "; cin>>W; cout<<"请依次输入每个物品的重量w和价值v,用空格分开: "; for(int i=1;i<=n;++i){ cin>>w[i]>>v[i]; } for(int j=1;j<=W;++j){ dp[j] = 0;//初始化第0行为0; } opt1(n,W); cout<<"装入购物车的最大价值为:"<<dp[W]<<endl; //测试dp[]数组结果 for(j=1;j<=W;++j){ cout<<dp[j]<<" "; } cout<<endl; system("pause"); return 0; }