原题链接:POJ1014
题意简述:给出六种价值分别为1,2,3,4,5,6的石头的个数,求是否可以公平的分成两份价值相同的石头。其中石头不可分割。
解题思路:就是说求是否可以分成两份,价值相同,可以使用幂级数型生成函数来求多重集的组合计数。详情步骤见吴永辉老师的《算法设计编程实验》。记录这题主要是为了熟悉幂级数型求多重集组合计数的代码写法。
代码实例:刚接触幂级数这一块,所以暂时没能力分析下述代码求幂级数的时空复杂度及优劣。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 6e3+5;
int a[10];
int c1[maxn],c2[maxn];
//用来读入数据,并判断是否结束。
bool Read(){
bool flag = false;
for(int i = 0;i < 6;i++){
scanf("%d",a+i);
if(a[i] >= 8){
if(a[i]&1) a[i] = 11;
else a[i] = 12;
}
if(a[i]) flag = true;
}
return flag;
}
//返回是否能分割
bool solve(){
int sum = 0;
for(int i = 0;i < 6;i++) sum += (i+1)*a[i];
if(sum&1) return false;
int value = sum/2;
memset(c1,0,sizeof c1);
memset(c2,0,sizeof c2);
for(int i = 0;i <= a[0];i++) c1[i] = 1;
/*其中c1是最终结果,而c2是中间结果,
每次假设展开两个括号,其结果暂时存放在2中,最终复制到c1
*/
for(int i = 1;i < 6;i++){
for(int j = 0;j <= value;j++)
if(c1[j]){
for(int k = 0;k + j <= value && k <= (i+1)*a[i];k += i+1)
c2[j+k] += c1[j];
}
memcpy(c1,c2,sizeof c2);
memset(c2,0,sizeof c2);
}
//上述代码是求解幂级数的方法
if(c1[value]) return c1[value];
return false;
}
int main(){
int cnt = 1;
while(Read()){
if(solve()) printf("Collection #%d:
Can be divided.
",cnt++);
else printf("Collection #%d:
Can't be divided.
",cnt++);
}
return 0;
}