NYOJ 49 开心的小明 (dp问题之01背包问题)
地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=49
思路:01背包问题
考虑使用dp问题 求解,定义一个递归式 opt[i][v] 表示前i个物品,在背包容量大小为v的情况下,最大的装载量。
opt[i][v] = max(opt[i-1][v] , opt[i-1][v-c[i]] + w[i]) //w[i]是容量为c[i]时的装载量
解释如下:
opt[i-1][v] 表示第i件物品不装入背包中,而opt[i-1][v-c[i]] + w[i] 表示第i件物品装入背包中。
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 int f[30001]; 5 int main() 6 { 7 int i,T,n,m,v,w; 8 cin>>T; 9 while(T--) 10 { 11 cin>>n>>m; //输入总钱数和物品最大个数 12 memset(f,0,sizeof(f)); 13 while(m--) 14 { 15 cin>>v>>w; //输入每个物品的价格和权值 16 for(i=n;i>=v;i--) 17 f[i]=max(f[i],f[i-v]+w*v); //这点是关键,f[i]表示当前容量为i时乘过权值的价格,f[i-v]+w*v表示在i-v这个容量时加上w*v与此时的f[i]容量相比较,取最大值,即最优解,转化为01背包问题去思考, 18 } 19 cout<<f[n]<<endl; 20 } 21 return 0; 22 }
别人的思路:
分析:01背包;d[i][j]表示在前 i 个物品中选择一些物品放入容量为 j 的背包中 第 i 个物体有放和不放两种情况
不放:就相当于在前 i-1 个物品中选择 即 d[i-1][j];
放:就是前 i-1 个物品只有 j-v 的容量让放 即 d[i-1][j-v]+w;
综合两种情况的最优是 d[i][j]=max{d[i-1][j] , d[i-1][j-v]+w};
空间优化如下:
d[i]表示容量为 i 的最优值,a[]表示物品的重量,b[]表示对应的价值量;
d[i]=max(d[i] , d[i-a[i]] + a[i]*b[i]);
1 #include<iostream> 2 #include<cstring> 3 #define M 30010 4 #define N 30 5 using namespace std; 6 7 int d[M],a[N],b[N]; 8 9 int max(int x,int y) 10 { 11 return x>y?x:y; 12 } 13 14 int main() 15 { 16 int test,m,n,i,j; 17 cin>>test; 18 while(test--) 19 { 20 cin>>m>>n; 21 for(i=1;i<=n;i++) cin>>a[i]>>b[i]; 22 memset(d,0,sizeof(d)); 23 for(i=1;i<=n;i++) 24 { 25 for(j=m;j>=a[i];j--) 26 { 27 d[j]=max(d[j],d[j-a[i]]+a[i]*b[i]); 28 } 29 } 30 cout<<d[m]<<endl; 31 } 32 return 0; 33 }