背包问题,这一类问题应用很广了。
本题可以根据特例优化一下。
#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <limits.h>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
const int MAX_N = 20001;
const int ARR_SIZE = 6;
int N, arr[ARR_SIZE], tbl[MAX_N * ARR_SIZE];
bool dividable(int sum)
{
if (sum & 1) return false;
int half = sum >> 1;
memset(tbl, 0, sizeof(int) * (half+1));
tbl[0] = 1;
for (int i = 0; i < ARR_SIZE; i++)
{
if (arr[i] == 0) continue;
int v = i+1;
for (int j = 0; j <= half; j++)
{
if (tbl[j]) tbl[j] = arr[i]+1;
else if (j >= v && tbl[j-v] > 1)
{
tbl[j] = tbl[j-v] - 1;
}
}
}
return tbl[half] > 0;
}
int main()
{
int minNum, sum, t = 1;
while (true)
{
minNum = INT_MAX;
sum = 0;
for (int i = 0; i < ARR_SIZE; i++)
{
scanf("%d", arr+i);
minNum = min(minNum, arr[i]);
sum += arr[i] * (i+1);
}
if (0 == sum) break;//结束条件
if (t > 1) putchar('\n');
printf("Collection #%d:\n", t++);
if (sum & 1)//剪枝
{
puts("Can't be divided.");
continue;
}
if (minNum)//优化
{
for (int i = 0; i < ARR_SIZE; i++)
{
arr[i] -= minNum;
sum -= (i+1) * minNum;
}
if (minNum & 1)
{
arr[2] += 1, arr[3] += 1;
sum += 3 + 4;
}
}
if (dividable(sum)) puts("Can be divided.");
else puts("Can't be divided.");
}
return 0;
}