题目描述
输入描述:
输出描述:
示例1
输入
1 0 1 2 0 0 1 0 0 0 1 1 0 0 0 0 0 0
输出
Collection #1: Can't be divided. Collection #2: Can be divided.
题意:
有价值分别是1~6的6种大理石,每种大理石的数量是ni,问能否将这些大理石分成完全相同的两部分?
题解:
这个题和hdu 2844 Coins做法基本一样,不过本题要稍微转变下思路
我们考虑用背包方法来做,题目给了数量,价值,却没有给总容量和体积。我们结合题意思考一下,要分成价值完全相同的两份,其实就是找到一份大理石,使得这一份的价值是总价值的一半。如果我们这样想,我们就会发现,总容量其实就是大理石总价值的一半,每个大理石的体积就是其价值,我们要做的就是找到“一些商品使得其体积满足总容量一半的情况是否存在”,这不就可以用混合背包来做。
对于数量多的用完全背包,对于数量少的用多重背包
代码:
#include<bits/stdc++.h> using namespace std; int a[8]; int sum=0; int dp[120005]; bool f=0;; void zerone(int cost,int val) { for(int i=sum;i>=cost;i--) { dp[i]=max(dp[i],dp[i-cost]+val); } } void complet(int cost) { for(int i=cost;i<=sum;i++) dp[i]=max(dp[i],dp[i-cost]+cost); } void mul(int cost,int val,int num) { if(cost*num>=sum) { complet(cost); return ; } for(int i=1;i<=num;i<<=1) { zerone(i*cost,i*val); num-=i; } zerone(num*cost,num*val); } int main() { int case1=0; while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]) { case1++; f=0; memset(dp,0,sizeof(dp)); if(a[1]==0&&a[2]==0&&a[3]==0&&a[4]==0&&a[5]==0&&a[6]==0)break; printf("Collection #%d:\n",case1); sum=a[1]*1+2*a[2]+3*a[3]+4*a[4]+5*a[5]+6*a[6]; if(sum%2) { printf("Can't be divided.\n"); printf("\n"); continue; } sum/=2; for(int i=1;i<=6;i++) { mul(i,i,a[i]);//花费,价值,数量 } if(dp[sum]==sum)f=1; if(f==1)cout<<"Can be divided."<<endl; else cout<<"Can't be divided."<<endl; cout<<endl; } return 0; }