01背包问题:
有一个体积为V的背包,有n件物品,每件物品的体积,价值分别为w[i],p[i];要从n件物品中选些放入背包中,使背包里物品的总价值最大。
动态方程:c[i][j]=max(c[i-1][j],c[i-1][j-w[i]]+p[i]).
有关动态方程方面的代码:
for (int i = 1; i <= n; i++) { for (int j = 1; j <= total_weight; j++) { if (w[i] > j) { c[i][j] = c[i-1][j]; } else { //也能够用<span style="font-family: KaiTi_GB2312;font-size:18px;">c[i][j]=max(c[i-1][j],c[i-1][j-w[i]]+p[i])取代以下的</span> if (c[i-1][j] > v[i]+c[i-1][j-w[i]]) { c[i][j] = c[i-1][j]; } else { c[i][j] = v[i] + c[i-1][j-w[i]]; } } } }在杭电2602中我们就能够非常舒服的用01背包解决:
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=2602
刚開始学习的人代码:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int c[1011][1011]; int max(int a,int b) { return a>b?a:b; } int knapsack(int m,int n) { memset(c,0,sizeof(c)); int i,j,val[1001],V[1001]; for(i=1;i<=n;i++) scanf("%d",&val[i]); for(i=1;i<=n;i++) scanf("%d",&V[i]); for (i = 1; i <= n; i++) { for (j = 1; j <= m; j++) { if (V[i] > j) { c[i][j] = c[i-1][j]; } else { c[i][j]=max(c[i-1][j],c[i-1][j-V[i]]+val[i]); } } } return (c[n][m]); } int main() { int t,n,m; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); printf("%d\n",knapsack(m,n)); } return 0; }
这个问题代码须要优化,降低时间空间复杂度,
(优化后代码)AC代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int c[1011]; int max(int a,int b) { return a>b?a:b; } int knapsack(int m,int n) { memset(c,0,sizeof(c)); int i,j,val[1001],V[1001]; for(i=1;i<n+1;i++) scanf("%d",&val[i]); for(i=1;i<n+1;i++) scanf("%d",&V[i]); for(i=1;i<n+1;i++) for(j=m;j>=V[i];j--) c[j]=max(c[j-V[i]]+val[i],c[j]); return(c[m]); } int main() { int t,n,m; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); printf("%d\n",knapsack(m,n)); } return 0; }