前一章讲到了用二维数组解背包问题,今天加深一个层次,用一维数组来做。其实本质上两者是一样的,但由于二维数组可以记录每次循环所得到的值,而一维数组只能记录上一次循环所得到的值,而且会在使用过程中不断覆盖。所以我们在第二个for循环中需要进行反向遍历。即i由1循环到N,内层的j由V循环到1。这与前一章的j由1循环到V相反。
状态转移方程:best[j]=max{best[j],best[j-volume[i]]+value[i]},大括号中的数记录的是上一次循环的值,这样便达到了与i-1一样的效果。
可能还是有些云里雾里吧。。。。这样,我们可以假设如果我们用一维数组时,依然使j正向遍历,那么会发生这么一种情况:我们在不断往后改变best[j]的值时需要用到上一次循环的值,但我们发现,由于在往后改值,所以之前的值都已经被改后的值覆盖了,这样结论就会出错。如果想不通,自己拿纸笔演算一遍就能茅塞顿开了。
代码如下:
#include <iostream>
using namespace std;
int max(int a,int b)
{
int temp=b;
if (a>b)temp=a;
return temp;
}
int main()
{
int V;
int best[100]={0};
int i,j;
int value[100]={0},volume[100]={0};
cin>>N>>V; for(i=1;i<=N;i++)cin>>value[i]>>volume[i];
for(j=0;j<=V;j++)
best[j]=0;
for(i=1;i<=N;i++)
for(j=V;j>=1;j--)
{
if (j>=volume[i])best[j]=max(best[j],best[j-volume[i]]+value[i]);
else best[j]=best[j];
}
cout<<best[V]<<endl;
}
return 0;
}