这题就是一个最基本的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有些许点了解!