zoukankan      html  css  js  c++  java
  • USACOCow 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;
    }
  • 相关阅读:
    C++ 算法03算法设计的常用思想
    C++ 算法02算法设计的基础
    C++ 算法01
    字符串Hash入门
    CSP2020总结
    关于树状数组的应用
    Cookies题解
    博客迁移
    斜率优化(转载)
    单调队列优化和决策单调性优化
  • 原文地址:https://www.cnblogs.com/ay27/p/2774243.html
Copyright © 2011-2022 走看看