题意:输入n1~n6 代表1~6的 个数,然后求这些数能不能通过分配达到value相等的状态
思路:多重背包(详见背包九讲) 能不能装满背包v/2的问题
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[100000];
int v;
bool flag;
void _com(int c , int w) {
for(int i = 0 ; i <= v ; i ++) {
if(i - c >= 0)
dp[i] = max(dp[i] , dp[i - c] + w);
if(dp[v] == v) {
flag = true;
return;
}
}
}
void _01(int c , int w) {
for(int i = v ; i >= 0 ; i --) {
if(i - c >= 0)
dp[i] = max(dp[i] , dp[i - c] + w);
if(dp[v] == v) {
flag = true;
return;
}
}
}
void _mul(int c , int w , int cnt) {
if(c*cnt>=v) { //如果满足条件就完全背包
_com(c , w);
return;
}
int k = 1;
while(k < cnt) { //否则就二进制优化
_01(k*c , k*w);
cnt -= k;
k = 2*k;
}
_01(cnt*c , cnt*w);
}
int main() {
int n[7];
int cas = 1;
while(cin>>n[1]>>n[2]>>n[3]>>n[4]>>n[5]>>n[6]) {
if(!n[1] && !n[2] && !n[3] && !n[4] && !n[5] && !n[6]) break;
flag = false;
v = 0;
for(int i = 1 ; i <= 6 ; i ++) {
v += i*n[i];
}
if(v%2==1) { //偶数肯定不行
printf("Collection #%d:\n",cas++);
printf("Can't be divided.\n\n");
continue;
}
v /= 2;
memset(dp , 0 , sizeof(dp));
for(int i = 1 ; i <= 6 ; i ++) {
_mul(i , i , n[i]);
if(flag) break;
}
printf("Collection #%d:\n",cas++);
if(flag) printf("Can be divided.\n\n");
else printf("Can't be divided.\n\n");
}
}