poj1276Cash Machine(多重背包)
2016-05-11 11:59
477 查看
我的理解:首先对于一件物品来说,如果这个物品的容量数目已经大于背包的总容量了,那么这与完全背包问题没有区别了。因为完全背包问题就是可以任意的往背包里面放物品,而这时这个物品的容量数目已经大于背包总容量了,所以,也就相当于在背包总容量的范围内,这个物品是可以支持 任意地往背包里面放物品。
如果这个物品的容量*数目小于背包的总容量,那么正常情况下,需要一件一件往里面放找最大值的。但是它的方法是:将第i种物品分成若干件01背包中的物品,其中每件物品有一个系数。这件物品的费用和价值均是原来的费用和价值乘以这个系数。令这些系数分别为1,2, 2的2次方,2的三次方,。。。2的k-1次方,最后是Mi - 2的k次方 + 1,且k是满足Mi - 2的k次方 + 1 的最大整数。例如,如果Mi为13,则相应的k=3,这种最多取13件物品的应被分成系数分别为1 2 4 6 的四件物品。
我觉得这里设计的很nice在于,正常情况下,举例来说这个物品有13件,我们需要一件一件放,放1件,2件,3件,。。。13件都放入,然后不断找最大值。但是上面的方法利用二进制,4个数,就做了13个数的事情。
发现 1 2 4 6 这四个数相互之间的和 就已经可以表示1到13的所有数,原因就在于当我放入1件物品,再放入2件物品找最大值的时候,实际上相当于我一下子放入了该物品的3件,所以实际上3是不需要我们再去实验的了。
//w是物品体积,n是物品种类,num[]是物品数量,price[]是物品价值,v[]是物品体积
这是最近写的
这是之前写的
如果这个物品的容量*数目小于背包的总容量,那么正常情况下,需要一件一件往里面放找最大值的。但是它的方法是:将第i种物品分成若干件01背包中的物品,其中每件物品有一个系数。这件物品的费用和价值均是原来的费用和价值乘以这个系数。令这些系数分别为1,2, 2的2次方,2的三次方,。。。2的k-1次方,最后是Mi - 2的k次方 + 1,且k是满足Mi - 2的k次方 + 1 的最大整数。例如,如果Mi为13,则相应的k=3,这种最多取13件物品的应被分成系数分别为1 2 4 6 的四件物品。
我觉得这里设计的很nice在于,正常情况下,举例来说这个物品有13件,我们需要一件一件放,放1件,2件,3件,。。。13件都放入,然后不断找最大值。但是上面的方法利用二进制,4个数,就做了13个数的事情。
发现 1 2 4 6 这四个数相互之间的和 就已经可以表示1到13的所有数,原因就在于当我放入1件物品,再放入2件物品找最大值的时候,实际上相当于我一下子放入了该物品的3件,所以实际上3是不需要我们再去实验的了。
//w是物品体积,n是物品种类,num[]是物品数量,price[]是物品价值,v[]是物品体积
这是最近写的
#include <iostream> #include <string.h> using namespace std; int v[1005],price[1005],num[1005]; long long dp[100005]; void Zero_Pack(int value,int vv,int w) { for(int i=w;i>=vv;i--) dp[i]=max(dp[i],dp[i-vv]+value); } void Complete_Pack(int value,int vv,int w) { for(int i=vv;i<=w;i++) dp[i]=max(dp[i],dp[i-vv]+value); } long long Pack(int v[],int price[],int num[],int n,int w) { for(int i=1;i<=n;i++) { if(num[i]*v[i]>w) { Complete_Pack(price[i],v[i],w); } else { int k=1; while(k<num[i]) { Zero_Pack(k*price[i],k*v[i],w); num[i]-=k; k=k<<1; } Zero_Pack(num[i]*price[i],num[i]*v[i],w); } } return dp[w]; } void init() { memset(dp,0,sizeof(dp)); memset(price,0,sizeof(price)); memset(num,0,sizeof(num)); memset(v,0,sizeof(v)); } int main() { ios::sync_with_stdio(false); int w,n; while(cin>>w>>n) { init(); for(int i=1;i<=n;i++) { cin>>num[i]>>price[i]; v[i]=price[i];//这里物品价值相当于物品体积 } long long ans=Pack(v,price,num,n,w); cout<<ans<<endl; } return 0; }
这是之前写的
相关文章推荐
- PHP动态规划解决0-1背包问题实例分析
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- PHP贪婪算法解决0-1背包问题实例分析
- PHP回溯法解决0-1背包问题实例分析
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解