0-1背包问题优化
则我们每次需要分配的内存是N*W,这确实不太好。
于是我们是否可以使用一个一维数组来代替前面算法的二维数组问题呢?
这好像是可以的,因为我们的想法是自底向上,其实对于W*N的二维数组,对于数组select[i][w]所代表的意思是
在背包容量为w,可以选的物品为前i个时它所能达到的最大价值,我们可以看到所记录的前面i个背包所能达到最
大的价值是浪费,我们所关心的只是在N个物品可选的情况下所能达到的最大价值。当然也是在容量可以W的可
选的情况下,,,,,,于是。。。。我们可以用一维数组表示啰。。。。因为有一维是浪费呢。。。。
#include "oneZeroPackage_Optimize.h"
int oneZeropkt_optimizeint(int pktVolum,int *prtVolum,int *prtValue,int prtLen){
struct Goods_op *goods=new Goods_op[prtLen+1];
for(int i=1;i<=prtLen; i++){
goods[i].value=prtValue[i];
goods[i].volum=prtVolum[i];
}
int *select=new int[pktVolum+1];
for(int i=0;i<=pktVolum;i++){
select[i]=0;
}
for(int i=1;i<=prtLen; i++){
for(int w=pktVolum; w>=goods[i].volum; w--){ //注意我们是在前一次的基础上进行这一次的计算
select[w]=Max((select[w]),(select[w-goods[i].volum]+goods[i].value));
}
}
return select[pktVolum];
}
#ifndef ONE_ZERO_PACKAGE_OPTIMIZE_H
#define ONE_ZERO_PACKAGE_OPTIMIZE_H
#define Max(a,b) a>b? a:b
struct Goods_op{
int value;
int volum;
};
int oneZeropkt_optimizeint(int pktVolum,int *prtVolum,int *prtValue,int prtLen);
#endif
#include"oneZeroPackage.h"
#include<iostream>
#include"oneZeroPackage_Optimize.h"
int main(){
int prtValue[4]={ 0,6,10,12};
int prtVolum[4]={ 0,1,2,3};
//std::cout<<oneZeropkt(5,prtVolum,prtValue,3)<<std::endl;
std::cout<<oneZeropkt_optimizeint(5,prtVolum,prtValue,3)<<std::endl;
}
由上面的代码知道我们确实只用了一个数组实现了这个问题,为什么可以呢?
上面说了,因为我们每次只是简单地用上次的结果计算当前这次的值 ,那么当这次算完了以后,上次的结果是不是没用了呢?
那是对的,哈哈。。。因为我们关心的只是这次啦 。。。于是有人想,是不是可以设两个数组呢,数组1用来存上次的,然后
数组2用来根据数组1存这次的结果,然后数组2在下一次计算时又成了上一的,则数组1成了这一次的。
我们看:在以前的算法代码中,
if(select[i-1][w-goods[i].volum]+goods[i].value>select[i-1][w]){
select[i][w]=select[i-1][w-goods[i].volum]+goods[i].value;
也就是根据i-1的计算结果来计算第i次的计算结果。