题意是有价值1-6的大理石,告诉你每种价值的个数问能不能分成总价值相同的两堆。
首先每种石头需要计算的个数不会超过6个。
比如对于1,如果最后分成的两堆都有1,那么我们可以预先把相同数量的1拿掉,最后使得只剩下某一堆中含有1,那么最多含有多少呢?应该是5。因为如果有大于等于6的1,那么我们总可以在另一堆中拿掉一块大理石,那后这一堆中拿掉相应数量的1补偿。所以1最多只有5块。
比如对于2,同样的我们假设只有一堆里面有2,那么最多有多少数量呢?如果另一堆里面有4或者6,那么我们总可以拿掉一个6或者4,然后在这一堆拿掉等价的2,也就是另一堆有4或者6的话这一堆最多只能有1个2。同样的另一堆有3和5同时存在的话,这一堆2最多只有3个。
经过这些分析发现其实每一堆的石头其实有很多都是没用的,所以我们可以模掉一个数。然后可以用最基本的DP解决了。
#include <bits/stdc++.h>
using namespace std;
#define maxn 121111
bool dp[maxn];
int a[maxn], tot;
int main () {
//freopen ("in", "r", stdin);
int kase = 0;
while (1) {
bool ok = 0;
tot = 0;
for (int i = 1; i <= 6; i++) {
int num;
scanf ("%d", &num);
if (num != 0)
ok = 1;
if (num > 6) {
num %= 6;
if (num == 0)
num = 6;
}
for (int j = 0; j < num; j++)
a[++tot] = i;
}
if (!ok)
break;
memset (dp, 0, sizeof dp);
dp[0] = 1;
int sum = 0;
for (int i = 1; i < tot; i++) {
for (int j = sum; j >= 0; j--) {
if (dp[j])
dp[j+a[i]] = 1;
}
sum += a[i];
}
sum = 0;
for (int i = 1; i <= tot; i++)
sum += a[i];
printf ("Collection #%d:\n", ++kase);
if ((sum&1) || dp[sum>>1] == 0)
printf ("Can't be divided.\n");
else printf ("Can be divided.\n");
printf ("\n");
}
return 0;
}