1014 Dividing 多重背包
来源:互联网 发布:推荐淘宝上的韩国泡菜 编辑:程序博客网 时间:2024/06/11 06:42
#include <iostream>#include <cstring>using namespace std;int n[7]; //价值为i的物品的个数int v; //背包容量int SumValue; //物品总价值bool flag; //标记是否能平分SumValueint dp[100000]; //状态数组int max(int a,int b){ return a>b?a:b;}/*完全背包*/void CompletePack(int cost,int weight){ for(int i=cost;i<=v;i++) { dp[i]=max(dp[i],dp[i-cost]+weight); if(dp[i]==v) //剪枝,当能够平分SumValue时退出 { flag=true; return; } } return;}/*01背包*/void ZeroOnePack(int cost,int weight){ for(int i=v;i>=cost;i--) { dp[i]=max(dp[i],dp[i-cost]+weight); if(dp[i]==v) //剪枝 { flag=true; return; } } return;}/*多重背包*/void MultiplePack(int cost,int weight,int amount){ if(cost*amount>=v) { CompletePack(cost,weight); return; } if(flag) //剪枝 return; /*二进制优化*/ int k=1; while(k<amount) { ZeroOnePack(k*cost,k*weight); if(flag) //剪枝 return; amount-=k; k*=2; } ZeroOnePack(amount*cost,amount*weight); return;}int main(){ int test=1; while(cin>>n[1]>>n[2]>>n[3]>>n[4]>>n[5]>>n[6]) { SumValue=0; //物品总价值 for (int i=1; i<=6; i++) SumValue+=i*n[i]; if (SumValue==0) break; if (SumValue%2) //sum为奇数,无法平分 { cout<<"Collection #"<<test++<<':'<<endl; cout<<"Can't be divided."<<endl<<endl; //注意有空行 continue; } v=SumValue/2; memset(dp,-1,sizeof(dp)); dp[0]=0; flag=false; for(int i=1; i<=6; i++) { MultiplePack(i,i,n[i]); if(flag) //剪枝 break; } if(flag) { cout<<"Collection #"<<test++<<':'<<endl; cout<<"Can be divided."<<endl<<endl; continue; } else { cout<<"Collection #"<<test++<<':'<<endl; cout<<"Can't be divided."<<endl<<endl; continue; } } return 0;}