这题就是一个最基本的0-1背包。刚学DP的人(比如说我)拿来上手应该是很不错的。题意就不多说了,应该都是很熟悉的了。我是看了《背包九讲》后做的,感觉上面说的很好!
一:下面这个程序是最基本的,就是没有什么优化的。
状态转移方程:Div[i][v]=max(Div[i-1][v],Div[i-1][v-w[i]]+c[i]);
#include <iostream> using namespace std; #define MAX 1002 int Div[MAX][MAX]; int c[MAX]; //价值 int w[MAX]; //体积 int max(int a,int b) { if(a>b) return a; return b; } int main() { int t,n,v,i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&v); memset(Div,0,sizeof(Div)); for(i=1;i<=n;i++) scanf("%d",&c[i]); for(i=1;i<=n;i++) scanf("%d",&w[i]); for(i=1;i<=n;i++) { for(j=0;j<=v;j++) { if(j>=w[i]) Div[i][j]=max(Div[i-1][j],Div[i-1][j-w[i]]+c[i]); else Div[i][j]=Div[i-1][j]; } } cout<<Div[n][v]<<endl; } return 0; }
二:由于时间复杂度已经不能再进行大的优化了。但发现空间使用是很大的,可以在空间上进行优化,既把记录数组Div由二维变成一维,这是可以的。这就是动态数组的思想,因为前面的数组用过之后,就可以用后面的数组去回滚掉!
动态转移方程:Div[v]=max(Div[v],Div[v-w[i]]+c[i]);
#include <iostream> using namespace std; #define MAX 1002 int Div[MAX]; int c[MAX]; //价值 int w[MAX]; //体积 int max(int a,int b) { if(a>b) return a; return b; } int main() { int t,n,v,i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&v); memset(Div,0,sizeof(Div)); for(i=1;i<=n;i++) scanf("%d",&c[i]); for(i=1;i<=n;i++) scanf("%d",&w[i]); for(i=1;i<=n;i++) { for(j=v;j>=w[i];j--) { Div[j]=max(Div[j],Div[j-w[i]]+c[i]); } } cout<<Div[v]<<endl; } return 0; }
三:后来,改了一小下,更好看了一下,但无大用:
#include <iostream> using namespace std; #define MAX 1002 int Div[MAX]; int c[MAX]; //价值 int w[MAX]; //体积 int main() { int t,n,v,i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&v); memset(Div,0,sizeof(Div)); for(i=1;i<=n;i++) scanf("%d",&c[i]); for(i=1;i<=n;i++) scanf("%d",&w[i]); for(i=1;i<=n;i++) { for(j=v;j>=w[i];j--) { if(Div[j-w[i]]+c[i]>Div[j]) Div[j]=Div[j-w[i]]+c[i]; } } cout<<Div[v]<<endl; } return 0; }
上面的三个程序自我感觉很是可以的,应该没有更好的方法了。希望借此入门,能对DP有些许点了解!