多重背包判断 sum 为偶数的时候 sum/2 可达不可达。
还是很简单的。 只要sum/2 那么 sum 一定可以分成两份。
多重背包解决。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MAXN 10+10
#define INF (1<<30)
#define mod 123456789
int main (){
int a[MAXN] = {0};
int kase = 0;
while(true){
int sum = 0;
for(int i = 1; i <= 6; i++){
scanf("%d",&a[i]);
sum += a[i]*i;
}
if(!sum)
break;
printf("Collection #%d:\n",++kase);
if(sum & 1){
printf("Can't be divided.\n\n");
continue;
}
int d[60000+10] = {0};
sum /= 2;
for(int i = 1; i <= 6; i++){
if(a[i]*i >= sum){
for(int j = i; j <= sum; j++){
if((j-i > 0 && d[j-i]) || j-i == 0)
d[j] = 1;
}
}
else if(a[i]){
int k = a[i]/2;
k /= 2;
int j;
for(j = 1; j <= k; j=(j<<1)){
for(int z = sum; z >= j*i; z--){
if((z-i*j > 0 && d[z-i*j]) || z-i*j == 0)
d[z] = 1;
}
}
int x = a[i]+1-j;
for(int z = sum; z >= i*x; z--){
if((z-i*x > 0 && d[z-i*x]) || z-i*x == 0)
d[z] = 1;
}
}
}
if(d[sum])
printf("Can be divided.\n");
else
printf("Can't be divided.\n");
printf("\n");
}
return 0;
}