A

题目链接:http://poj.org/problem?id=3624

题意:

经典0—1背包问题,有n个物品,编号为i的物品的重量为w[i],价值为v[i],现在要从这些物品中选一些物品装到一个容量为m的背包中,使得背包内物体在总重量不超过m的前提下价值尽量大. 其中dp[i,j]表示的是前i个物品装入容量为j的背包里所能产生的最大价值,w[i]是第i个物品的重量,d[i]是第i个物品的价值。如果某物品超过背包容量,则该物品一定不放入背包,问题变为剩余i-1个物品装入容量为j的背包所能产生的最大价值;否则该物品装入背包,问题变为剩余i-1个物品装入容量为j-w[i]的背包所能产生的最大价值加上物品i的价值d[i]

这道题一开始是用二维数组写的,后来发现这道题的m有点大,二维数组开不了那么大,改用一维。

用此时的i行的数据来覆盖i-1行的。

但是要逆序 j从m到w[i],以j=m.0的顺序推f[j],这样才能保证推f[j]时f[j-c[i]]保存的是状态f[i-1][j-c[i]]的值。

如果将j的循环顺序从上面的逆序改成顺序的话,那么则成了f[i][j]由f[i][j-c[i]]推知,与本题意不符。




#include<iostream> #include<cstring> #include<stdio.h> #include<math.h> #include<algorithm> using namespace std; const int maxn=10200; #define N 14010 int n,m; int f[N]; int w[N]; int d[N]; int main() { int a,b,c,m; while(~scanf("%d%d",&n,&m)) { memset(w,0,sizeof(w)); memset(d,0,sizeof(d)); memset(f,0,sizeof(f)); for(int i=1; i<=n; i++) scanf("%d%d",&w[i],&d[i]); for(int i=1; i<=n; i++) for(int j=m; j>=w[i]; j--)///当此时的j小于此时的w[i]时,循环不再进行下去 f[j] = max(f[j],f[j-w[i]]+d[i]); ///与i-1时的f[j]来与i-1时的f[j减去此时w[i]]加上此时的d[i]比较; printf("%d ",f[m]); } return 0; }
原文地址:https://www.cnblogs.com/biu-biu-biu-/p/5735618.html