题目描述:
有 N 件物品和容量为 M 的背包,第 i 件物品的体积是 w[i],价值是 d[i],求解将哪些物品放入背包可以使价值总和最大,每种物品只有一件,可以选择放或者不放。(N<=3500 , M<=13000)
第一行有两个数据,分别是 N 和 M,接下来 N 行,分别输入每件物品的体积和价值。
样例输入
4 6 1 4 2 6 3 12 2 7
样例输出
23
看过很多大神们写的有关这个问题的解法,我来分享一种不同的解法,或者说是稍微改进了一下,即不用二维数组,有大神提到过滚动数组,原谅鄙人学识浅薄,实在转化不过来了,即用两个一维数组实现递推,至于此题涉及到的递推思想,我就不再赘述了。简单说一下,对于上例,给上面物品分别标记 A,B,C,D,思想就是当只有一个A物品时,背包容量从 1~6 的最大价值分别是4,4,4,4,4,4, 最大价值是 4 , 然后再加入一个B物品后,背包从 1~6 所能容纳的最大价值分别是 4,6,10,10,10,10,最大价值是 10,继续,三个物品,背包所能容纳的最大价值分别是4,6,12,16,18,22,最大价值是 22,再加入D物品,最大价值为 23 。状态迁移方程: F[i][j] = max(F[i-1][j],F[i-1][j-weight[i]]+value[i]); 分别代表取或不取。i-1 是上一种状态得到的结果。
poj原题链接:
http://poj.org/problem?id=3624
AC代码:
#include <iostream> #include <cstring> using namespace std; int N,M; int sum(int bag[],int bag1[],int w[],int v[]) { int n = 1; for(int i = 1; i <= N; i++) { for(int j = 1; j <= M; j++) { if(n%2 == 1) { if(j < w[i]) bag[j] = bag1[j]; else bag[j] = max(bag1[j],bag1[j-w[i]]+v[i]); } else { if(j < w[i]) bag1[j] = bag[j]; else bag1[j] = max(bag[j],bag[j-w[i]]+v[i]); } } n++; } if(n%2 == 0) return bag[M]; else return bag1[M]; } int main() { cin>>N>>M; int value[N + 1]; int weight[N + 1]; int bag[M+1],bag1[M+1]; memset(bag,0,4*(M+1)); memset(bag1,0,4*(M+1)); memset(weight,0,4*(N+1)); memset(value,0,4*(N+1)); for(int i = 1; i<=N; i++) cin>>weight[i]>>value[i]; cout<<sum(bag,bag1,weight,value)<<endl; return 0; }