hdu--1059--多重背包||DP||搜索
碎碎念-----
突然 觉得好无聊~~ 还好 只有4天了~~
直接上题吧~~
使用多重背包的代码是转自---键盘上的舞者---- 写得特别有想法
使用dp的代码是porker写的..
使用搜索的 我一开始是将价值从低到高搜索的 这样TLE了,,因为速度实在是太慢了 假如有arr[k]个 那么我要有arr[k]+1个操作...
但是 按价值从高到低的搜索 只要遵循 尽量在不到sum/2的时候去搜就是了 有就添加进来...但这个方法的正确性 没有得到证明...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 using namespace std; 3 int arr[7]; 4 int sum, cnt = 1; 5 6 bool dp[7][120001]; 7 8 int main() 9 { 10 cin.sync_with_stdio(false); 11 while (cin >> arr[1]) 12 { 13 sum = 0; 14 sum += arr[1]; 15 for (int i = 2; i <= 6; i++) 16 { 17 cin >> arr[i]; 18 sum += arr[i] * i; 19 } 20 if (!sum) 21 break; 22 cout << "Collection #" << cnt++ << ":" << endl; 23 if (sum & 1) { 24 cout << "Can't be divided." << endl << endl; 25 continue; 26 } 27 memset(dp, false, sizeof(dp)); 28 dp[0][0] = true; 29 for (int i = 1; i <= 6; i++) { 30 for (int j = sum; j >= 0; j--) { 31 if (dp[i - 1][j] == false) continue; 32 for (int k = 0; k <= arr[i]; k++) { 33 if (j + k*i >= sum) break; 34 if (dp[i][j + k*i]) break; 35 dp[i][j + k*i] = true; 36 } 37 } 38 } 39 if (dp[6][sum / 2]) { 40 cout << "Can be divided." << endl; 41 } 42 else { 43 cout << "Can't be divided." << endl; 44 } 45 cout << endl; 46 } 47 return 0; 48 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 6 int dp[100000]; 7 8 int main() 9 { 10 int a[11],sum,v,i,j,k,cnt,cas = 1; 11 while(~scanf("%d",&a[1])) 12 { 13 sum = a[1]; 14 for(i = 2;i<=6;i++) 15 { 16 scanf("%d",&a[i]); 17 sum+=i*a[i]; 18 } 19 if(!sum) 20 break; 21 printf("Collection #%d:\n",cas++); 22 if(sum%2)//总和为奇数,必定不能平分 23 { 24 printf("Can't be divided.\n\n"); 25 continue; 26 } 27 v = sum/2; 28 memset(dp,0,sizeof(dp)); 29 dp[0] = 1; 30 for(i = 1;i<=6;i++) 31 { 32 if(!a[i]) 33 continue; 34 for(j = 1;j<=a[i];j*=2)//二进制优化 35 { 36 cnt = j*i; 37 for(k = v;k>=cnt;k--) 38 { 39 if(dp[k-cnt])//必须前面的能够放入背包,现在的才能放入背包 40 dp[k] = 1; 41 } 42 a[i]-=j; 43 } 44 cnt = a[i]*i;//剩下的 45 if(cnt) 46 { 47 for(k = v;k>=cnt;k--) 48 { 49 if(dp[k-cnt]) 50 dp[k] = 1; 51 } 52 } 53 } 54 if(dp[v]) 55 printf("Can be divided.\n\n"); 56 else 57 printf("Can't be divided.\n\n"); 58 } 59 60 return 0; 61 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 using namespace std; 3 int arr[7]; 4 int sum , cnt = 1; 5 bool flag; 6 7 void dfs( int pos , int cnt ) 8 { 9 if( cnt*2 == sum ) 10 { 11 flag = true; 12 return; 13 } 14 if( flag || cnt*2>sum ) 15 { 16 return; 17 } 18 for( int i = pos ; i>=1 ; i-- ) 19 { 20 if( arr[i] ) 21 { 22 if( cnt+i<=sum/2 ) 23 { 24 arr[i]--; 25 dfs( i , cnt+i ); 26 if( flag ) 27 break; 28 } 29 } 30 } 31 } 32 33 int main() 34 { 35 cin.sync_with_stdio(false); 36 while( cin >> arr[1] ) 37 { 38 flag =false; 39 sum = 0; 40 sum += arr[1]; 41 for( int i = 2 ; i<=6 ; i++ ) 42 { 43 cin >> arr[i]; 44 sum += arr[i]*i; 45 } 46 if( !sum ) 47 break; 48 cout << "Collection #"<< cnt++ <<":"<<endl; 49 if( sum&1 ) 50 { 51 cout << "Can't be divided." << endl << endl; 52 continue; 53 } 54 dfs( 6 , 0 ); 55 if( flag ) 56 cout << "Can be divided." << endl << endl; 57 else 58 cout << "Can't be divided." << endl << endl; 59 } 60 return 0; 61 }
today:
你看别人说他千般不好 他说过一句没有。
悲伤的人总是在笑。
just follow your heart