背包总结:
01背包:每种背包只有一个,且有放与不放两种选择;
完全背包:每种背包有无限个,且可以选择放n个或不放;
多重背包:每种背包的数目为规定个,可以选择放n个(不大于规定个)或不放;
一般可以总结出一个公式:dp[i][j]=max{dp[i-1][j],dp[i-1][j-c[i]]+w[i]}
而为了使空间更加的节省,可以将二维的数组变为一维数组:dp[i]=max{dp[i],dp[i-c[j]]+w[j]}
可是,这样一来,前面的两重for循环又会因此而不同:
对于01背包:for(i from 1 to n)for(j from w to 0)
第二重一定要从最大容量到最小,因为由于只有一维数组,表达的范围有限,所以如果从最小到最大,那么就会使每种物品放了不止一次。
而对于完全背包:for(i from 1 to n)for(j from 0 to w)
这时的情况和01背包刚好相反,所以第二重循环就刚好相反。
对于多重背包,则需要在第二重循环时,分情况讨论:
如果c[i]*w[i]<w,那么情况和完全背包相同(c[i]表示第i个物品的数目,w[i]表示第i个物品的重量);
else 需要把一种类型的物品化为多种不同的物品;再按照01背包的模式计算。在化为多种物品的过程中,可以通过二进制的转换,将时间复杂度简化;eg. 13=1+2+4+6;这样一来,四个数可以表示任何1~13的数了,那么就只需要将一个物品转化为四个,再用01背包计算即可。
for(i from 1 to n)if(c[i]*w[i]<w) 完全背包
else temp=c[i]; temp1=1;
while(temp>temp1){
01bag(temp);temp1-=temp;
temp=temp*2;
}
01bag(temp1);
这样一来,时间复杂度就变成了O(n*w*log)
完全背包还有一个O(n*m)的算法,暂时还没有研究。。。
01背包:每种背包只有一个,且有放与不放两种选择;
完全背包:每种背包有无限个,且可以选择放n个或不放;
多重背包:每种背包的数目为规定个,可以选择放n个(不大于规定个)或不放;
一般可以总结出一个公式:dp[i][j]=max{dp[i-1][j],dp[i-1][j-c[i]]+w[i]}
而为了使空间更加的节省,可以将二维的数组变为一维数组:dp[i]=max{dp[i],dp[i-c[j]]+w[j]}
可是,这样一来,前面的两重for循环又会因此而不同:
对于01背包:for(i from 1 to n)for(j from w to 0)
第二重一定要从最大容量到最小,因为由于只有一维数组,表达的范围有限,所以如果从最小到最大,那么就会使每种物品放了不止一次。
而对于完全背包:for(i from 1 to n)for(j from 0 to w)
这时的情况和01背包刚好相反,所以第二重循环就刚好相反。
对于多重背包,则需要在第二重循环时,分情况讨论:
如果c[i]*w[i]<w,那么情况和完全背包相同(c[i]表示第i个物品的数目,w[i]表示第i个物品的重量);
else 需要把一种类型的物品化为多种不同的物品;再按照01背包的模式计算。在化为多种物品的过程中,可以通过二进制的转换,将时间复杂度简化;eg. 13=1+2+4+6;这样一来,四个数可以表示任何1~13的数了,那么就只需要将一个物品转化为四个,再用01背包计算即可。
for(i from 1 to n)if(c[i]*w[i]<w) 完全背包
else temp=c[i]; temp1=1;
while(temp>temp1){
01bag(temp);temp1-=temp;
temp=temp*2;
}
01bag(temp1);
这样一来,时间复杂度就变成了O(n*w*log)
完全背包还有一个O(n*m)的算法,暂时还没有研究。。。