动态规划:0-1背包问题(二)

前一章讲到了用二维数组解背包问题,今天加深一个层次,用一维数组来做。其实本质上两者是一样的,但由于二维数组可以记录每次循环所得到的值,而一维数组只能记录上一次循环所得到的值,而且会在使用过程中不断覆盖。所以我们在第二个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;  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值