hdu 1059 Dividing
2013-10-01 09:44
246 查看
1.题目
http://acm.hdu.edu.cn/showproblem.php?pid=10592.分析
1.本题要求平分物品,所以资源上限应该为总价值的一半,因此当资源限制为奇数的时候无法平分,应该去掉;2.为了要达到价值的一半而进行物品的选择,可以按照01背包的思路针对每类物品的每一个商品进行01背包,记录中间产生的值和资源限制进行比较;但是,01背包速度较慢,没有优化,详见《背包九讲》。
3.由于不是要完全都选择,只是选择其中的部分,可以对每一类物品使用多重背包来搞即可,同时可以利用多重背包的优化策略。根据最后的要求判断最优值是否等于资源限制的一半即可。
3.复杂度
时间复杂度是O(V*Σn[i]);空间复杂度O(V);4.涉及内容
动态规划5.感想
关于背包初始化有两种情况:1)背包不要求装满:初始化的时候,在任何一个价值限制下,0肯定都满足题目要求不装满,根据动态规划由前边导出后边值的时候0是一个满足条件的值。
2)背包要求装满:初始化的时候,在0价值限制下,0肯定满足要求装满;在非零价值线之下,由于是初始化,自然没有任何数值满足条件要求,因此可以初始化为整形最大值或者整形最小值,此时,在推导的时候都需要考虑上一次的价值是否是在装满条件下的(即不是整形最大值或者最小值,而是新计算出来的值)。判断的方法:当初始化为最小值的时候,用f[v]=max{f[v],f[v-cost]+weight};当初始化为最大值的时候,用f[v]=min{f[v],f[v-cost]+weight};或者用if判断f[v-cost]是否是初始化的值即可。
对于本题这种组合形式,可以再01背包函数和完全背包函数中各自加上装满情况的初始化,自己判断。最后,将结果和初始化值作比较即可。
第二个感悟还是要把经典题目弄清楚,弄明白!!!!
6.代码
#include <iostream> using namespace std; int c1059[7],f1059[60005]; long total1059=0,limitvalue1059=0,num1059=0; bool cin1059() { memset(c1059,0,sizeof(c1059)); memset(f1059,0,sizeof(f1059)); total1059=limitvalue1059=0; cin>>c1059[1]>>c1059[2]>>c1059[3]>>c1059[4]>>c1059[5]>>c1059[6]; for(int i=6;i>=1;--i) { total1059+=c1059[i]*i; } return (c1059[1]||c1059[2]||c1059[3]||c1059[4]||c1059[5]||c1059[6]); } int max1059(int a,int b) { return a>b?a:b; } void ZeroOnePack1059(int c,int w) { for(int i=limitvalue1059;i>=c;--i) f1059[i]=max1059(f1059[i],f1059[i-c]+w); } void CompletePack1059(int c,int w) { for(int i=c;i<=limitvalue1059;++i) f1059[i]=max1059(f1059[i],f1059[i-c]+w); } void MultiplePack1059(int c,int w,int n) { if(c*n>=limitvalue1059) { CompletePack1059(c,w); } else { int k=1; while(k<n) { ZeroOnePack1059(c*k,w*k); n-=k;//一下两条语句的顺序很重要 k+=k; } ZeroOnePack1059(c*n,w*n); } } int main() { //freopen("in.txt","r",stdin); while(cin1059()) { if(total1059%2) { cout<<"Collection #"<<++num1059<<":"<<endl<<"Can't be divided."<<endl<<endl; continue; } limitvalue1059=total1059/2; for(int i=1;i<=6;++i) { MultiplePack1059(i,i,c1059[i]); } if(f1059[limitvalue1059]==limitvalue1059) cout<<"Collection #"<<++num1059<<":"<<endl<<"Can be divided."<<endl<<endl; else cout<<"Collection #"<<++num1059<<":"<<endl<<"Can't be divided."<<endl<<endl; } return 0; }
7.参考文献
1./article/5183073.html2.http://java-mans.iteye.com/blog/1646457
3./article/1969921.html
相关文章推荐
- HDU-1059-Dividing-多重背包
- HDU-1059-Dividing
- HDU 1059 Dividing dp背包题解
- hdu1059 Dividing(多重背包二进制优化)
- HDU1059 && POJ1014 :Dividing(多重背包)
- hdu 1059 Dividing(dp+二进制优化)
- hdu1059 Dividing ——多重背包
- HDU1059 Dividing(多重背包,二进制优化,模板题)
- 【二进制拆分多重背包】【HDU1059】【Dividing】
- hdu1059 Dividing (多重背包)
- HDU 1059 Dividing 多重背包动态规划
- HDU 1059 Dividing (多重背包问题)
- Hdu 1059 Dividing -- 多重背包
- hdu 1059 Dividing (多重背包 )
- Dividing--hdu1059(动态规划)
- hdu 1059 Dividing
- HDU 1059 Dividing(多重背包)
- hdu1059 Dividing(多重背包+二进制优化)
- HDU1059——多重部分和问题——Dividing
- HDU 1059 Dividing【多重背包】