求可行性解的问题,多重背包解
一开始直接上多重背包一般解法,先是wa,然后TL了,后来又试了别的方法,wa,再上网搜了下看了别人的,后来改用的二进制拆分
//二进制拆分
#include <bits/stdc++.h>
using namespace std;
#define maxn 300050
int d[maxn];//存可行性解的
int n[7]; //存每种物品存放了多少个
int num[maxn];
int cou;
void add(int k,int n) //多重背包的二进制拆分
{
int i,x,tmp = 0;
for(i=0; ; i++)
{
x = 1<<i;
if( tmp + x > k )
break;
tmp += x;
num[cou++] = x*n;
}
x = k - tmp;
if( x != 0 )
num[cou++] = n*x;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int testnum=1;
while(scanf("%d%d%d%d%d%d",&n[1],&n[2],&n[3],&n[4],&n[5],&n[6])!=EOF){
int sum=0;
for (int i=1;i<=6;i++){
sum+=(n[i]*i);
}
if (sum==0) break;
printf("Collection #%d:\n",testnum++);
if (sum&1){
printf("Can't be divided.\n\n");
continue;
}
sum=sum/2;
cou=0;
add(n[1],1);add(n[2],2);add(n[3],3);add(n[4],4);add(n[5],5);add(n[6],6);
memset(d,0,sizeof(d));
for (int i=0;i<cou;i++){
for (int s=sum;s>=num[i];s--){
d[s]=max(d[s],d[s-num[i]]+num[i]);
}
}
int ok=0;
if (d[sum]==sum) ok=1;
if (ok) printf("Can be divided.\n\n");
else printf("Can't be divided.\n\n");
}
return 0;
}