USACO-Cow Pedigrees

来源:http://ace.delos.com/usacoprob2?a=T9Gq2i9yzJN&S=nocows

题目要求的是,用N个结点能够构造多少个高为K的二叉树,要求二叉树的结点的度为0或2。

首先,我们要关注的是树的高度和结点数。再者,这题的所有结点的度都为0或2。

考虑到结点度的特殊性,如果把高为K的树的根结点删去,则生成两个高为K-1的子树T1和T2,它们的结点数和为N-1

1.设左子树的结点数为N1,则右子树的结点数为N-N1-1;

2.设函数P表示满足题目条件的树的个数,则结果result(N)=P(N1)*P(N-N1-1);

3.由于k1的不确定性,result(N)=∑ P(N1)*P(N-N1-1)  ,其中(N1=1,3,5…,N1<=N-2)

4.对于T1和T2用同样的方法分解,很容易看到这是递归定义的,完全满足DP的两个条件:无后效性和最优子结构;
5.方程的设计:
  设F[i][j]表示高小于等于i,节点数为j的满足题目要求的树的数目,则易得:
    F[i][j]=∑F[i-1][k]*F[i-1][j-k-1]  {k=1,3,...j-2}
易得边界条件:F[i][1]=1
结果为:F[k][n]-F[k-1][n]

当然,这里的结果需要需要模一个数,而如果在DP过程中边模边算,则可能出现F[k][n]-F[k-1][n]<0的情况,解决的办法是(F[k][n]-F[k-1][n]+V)%V,V就是9901

/*
ID:ay27272
PROG:nocows
LANG:C++
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>

using namespace std;

#define V 9901

int f[200][200];

int main()
{
    freopen("nocows.in","r",stdin);
    freopen("nocows.out","w",stdout);

    int n,h;
    scanf("%d%d",&n,&h);

    memset(f,0,sizeof(f));
    for (int i=1;i<=h;i++)
        f[i][1]=1;

    for (int i=1;i<=h;i++)
        for (int j=3;j<=n;j+=2)
            for (int k=1;k<=j-2;k+=2)
            f[i][j]=(f[i][j]+f[i-1][k]*f[i-1][j-k-1])%V;
    printf("%d\n",(f[h][n]-f[h-1][n]+V)%V);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值