1. 程式人生 > >[多重背包+二進制優化]HDU1059 Dividing

[多重背包+二進制優化]HDU1059 Dividing

scan style vid ide show ems lose while span

題目鏈接

題目大意:

兩個人要把一堆寶珠,在不能切割的情況下按照價值平分,他們把寶珠分成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 }
代碼實現

[多重背包+二進制優化]HDU1059 Dividing