http://www.hawstein.com/posts/dp-knapsack.html
http://www.cnblogs.com/wwwjieo0/archive/2013/04/01/2991238.html
http://blog.csdn.net/mu399/article/details/7722810
n颗宝石,体积v[i] 价值w[i] ,背包体积C
/**0-1 knapsack d(i, j)表示前i个物品装到剩余容量为j的背包中的最大重量**/ #include<cstdio> using namespace std; #define MAXN 1000 #define MAXC 100000 int V[MAXN], W[MAXN],x[MAXN]; int d[MAXN][MAXC]; int main(){ freopen("data.in", "r", stdin);///重定向输入流 freopen("data.out", "w", stdout);///重定向输出流 int n, C; while(scanf("%d %d", &n, &C) != EOF){ for(int i=0; i<n; ++i) scanf("%d %d", &V[i], &W[i]); for(int i=0; i<=n; ++i){ for(int j=0; j<=C; ++j){ d[i][j] = i==0 ? 0 : d[i-1][j]; if(i>0 && j>=V[i-1]) d[i][j] =max(d[i-1][j],d[i-1][j-V[i-1]]+W[i-1]); } } printf("%d ", d[n][C]);///最终求解的最大价值 ///输出打印方案 int j = C; for(int i=n; i>0; --i){ if(d[i][j] > d[i-1][j]){ x[i-1] = 1; j = j - V[i-1];///装入第i-1个宝石后背包能装入的体积就只剩下j - V[i-1] } } for(int i=0; i<n; ++i) printf("%d ", x[i]);///x[i]==1,即第i+1个放入 printf(" "); } fclose(stdin); fclose(stdout); return 0; }
5 10
4 9
3 6
5 1
2 4
5 1
4 9
4 20
3 6
4 20
2 4
5 10
2 6
2 3
6 5
5 4
4 6
优化:
当一个问题找到一个放心可靠的解决方案后, 我们往往就要考虑一下是不是有优化方案了。
该算法的时间复杂度是O(nC), 即时间都花在两个for循环里了,这个应该是没办法再优化了。
再看看空间复杂度, 数组d用来保存每个状态的值,空间复杂度为O(nC);
数组V和W用来保存每个宝石的体积和价值,空间复杂度为O(n)。
程序总的空间复杂度为 O(nC),这个是可以进一步优化的。
首先,我们先把数组V和W去掉, 因为它们没有保存的必要,改为一边读入一边计算:
int v=0,w=0; for(int i=0; i<=n; ++i){ if(i>0) scanf("%d%d",&v,&w); for(int j=0; j<=C; ++j){ d[i][j] = i==0 ? 0 : d[i-1][j]; if(i>0 && j>=v) d[i][j] =max(d[i-1][j],d[i-1][j-v]+w); } } printf("%d ", d[n][C]);///最终求解的最大价值
空间优化2,空间复杂度仅为O(C)
#include<cstdio> #include "cstdlib" #include "cstring" using namespace std; #define MAXN 1000 #define MAXC 100000 int main(){ freopen("data.in", "r", stdin);///重定向输入流 freopen("data.out", "w", stdout);///重定向输出流 int n, C; while(scanf("%d %d", &n, &C) != EOF){ int* d = (int*)malloc((C+1)*sizeof(int)); memset(d, 0, (C+1)*sizeof(int)); int v=0,w=0; for(int i=0; i<=n; ++i){ if(i>0) scanf("%d%d",&v,&w); for(int j=C; j>=0; j--){ if(i>0 && j>=v) d[j] =max(d[j],d[j-v]+w); } } printf("%d ", d[C]);///最终求解的最大价值 } fclose(stdin); fclose(stdout); return 0; }