感觉就是一个爆搜的题目,但是却被列为DP了...
令flag[i] == true表示i这个数据可以分配成功
则我们只需依次遍历直到出现flag[sum/2]==true
或已遍历完小于sum/2的部分但是没有flag[sum/2]==true
这题有个地方比较坑就是题目中说了所有堆数之和最大为20000
但是应该指的是每堆最大20000,害的re了好几次。。。
0ms代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 120010
using namespace std;
int a[10];
bool flag[MAXN];
bool dfs(int sum) {
int tmp, maxv;
maxv = 0;
if(sum % 2)
return false;
sum >>= 1;
memset(flag, false, sizeof(flag));
flag[0] = true;
for(int i=1; i<=6; ++i) {
if(a[i] > 0) {
for(int j=maxv; j>=0; --j) {//这里要倒着搜,否则一组数据会重复使用,原因是不让后面的flag[tmp]对当前循环产生影响
if(flag[j]) {
for(int k=1; k<=a[i]; ++k) {
tmp = j+k*i;
if(tmp == sum)
return true;
if(tmp>(sum) || flag[tmp])
break;
flag[tmp] = true;
}
}
}
}
maxv += a[i]*i;
maxv = max(sum, maxv);
}
return false;
}
int main(void) {
int sum, cas = 1;
bool tmp;
while(scanf("%d", &a[1]) != EOF) {
sum = a[1];
for(int i=2; i<=6; ++i) {
scanf("%d", &a[i]);
sum += a[i]*i;
}
if(sum == 0)
break;
tmp = dfs(sum);
printf("Collection #%d:\n", cas++);
if(sum < 0)
tmp = false;
if(tmp)
printf("Can be divided.\n\n");
else printf("Can't be divided.\n\n");
}
return 0;
}