POJ1014 Dividing(幂级数型生成函数)

版权声明:个人笔记,仅供复习 https://blog.csdn.net/weixin_41162823/article/details/86625373

原题链接: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:\nCan be divided.\n\n",cnt++);
        else printf("Collection #%d:\nCan't be divided.\n\n",cnt++);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41162823/article/details/86625373