HDU1059 【DP·二进制数优化】
题意:
有6种不同价值的物品,然后问你能不能分成两半使得两堆价值相等;
思路:
一共有20000*6=120000 多的价值,
总共背包有20000个,价值最大是120000,看看能不能DP到value/2就好了,所以DP数组可以开60000;
价值乘以背包数,复杂度好大?
我们知道一个数的组成可以搞成一个二进制,所以对于每个背包的数量,都可以搞成几个二进制数的背包数量
有6种不同价值的物品,然后问你能不能分成两半使得两堆价值相等;
思路:
一共有20000*6=120000 多的价值,
总共背包有20000个,价值最大是120000,看看能不能DP到value/2就好了,所以DP数组可以开60000;
价值乘以背包数,复杂度好大?
我们知道一个数的组成可以搞成一个二进制,所以对于每个背包的数量,都可以搞成几个二进制数的背包数量
那么就是有那么多背包,简单DP一下就好了;
#include<bits/stdc++.h> using namespace std; const int N=6e4+10; int num[7]; bool dp[N]; int main() { int cas=1; while(1) { bool flag=false; int sum=0; for(int i=1;i<=6;i++) { scanf("%d",&num[i]); sum+=num[i]*i; if(num[i]) flag=true; } if(!flag) break; printf("Collection #%d:\n",cas++); if(sum%2) { printf("Can't be divided.\n\n"); continue; } memset(dp,0,sizeof(dp)); sum/=2; int k,w; dp[0]=true; for(int i=1;i<=6;i++) { k=1; while(k<=num[i]) { w=k*i; for(int j=sum;j>=w;j--) { if(dp[j-w]) dp[j]=1; } num[i]-=k; k<<=1; } w=num[i]*i; for(int j=sum;j>=w;j--) if(dp[j-w]) dp[j]=1; } if(dp[sum]) printf("Can be divided.\n\n"); else printf("Can't be divided.\n\n"); } return 0; }