题目大意:
两个人要把一堆宝珠,在不能切割的情况下按照价值平分,他们把宝珠分成6种价值,每种价值的宝珠n个。 n<=200000
思考:
首先如果加和下来的价值是一个偶数 那么还分毛啊,直接gg.
之后多重背包二进制优化 转换为 01背包。
我们可以把价值 同时当做宝珠的空间和价值。
那么我们现在要求的是 在 空间为一半的情况下,能否找到价值为 一半的情况。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 int dp[200005],n[7],V[105],W[100]; 5 6 int main(){ 7 int k=0; 8 while(scanf("%d%d%d%d%d%d",&n[1],&n[2],&n[3],&n[4],&n[5],&n[6])!=EOF && (n[1]||n[2]||n[3]||n[4]||n[5]||n[6])){ 9 printf("Collection #%d:\n",++k); 10 int i,j,sum=0,mid; 11 for(i=1;i<=6;i++) sum+=i*n[i]; 12 if(sum%2){ 13 printf("Can‘t be divided.\n\n"); 14 continue; 15 } 16 else mid = sum/2; 17 memset(dp,0,sizeof(dp)); //切记不要忘了初始化 18 int count=0,temp,flag=1; 19 //这块是二进制优化 20 for(i=1;i<=6;i++){ 21 temp=1; 22 while(n[i]>=temp){ 23 V[++count]=i*temp; 24 W[count]=i*temp; 25 n[i]-=temp; 26 temp*=2; 27 } 28 if(n[i]>0){ 29 V[++count]=i*n[i]; 30 W[count]=i*n[i]; 31 } 32 } 33 //上面是二进制优化 34 for(int i=1;i<=count && flag;i++) 35 for(int j=mid;j>=V[i] && flag;j--){ 36 dp[j] = std::max(dp[j],dp[j-V[i]]+W[i]); 37 if(dp[j]==mid){ 38 printf("Can be divided.\n\n"); 39 flag=0; 40 } 41 } 42 if(flag){ 43 printf("Can‘t be divided.\n\n"); 44 } 45 } 46 return 0; 47 }
代码实现
时间: 2024-10-24 12:46:39