Section 2.3-nocows

来源:互联网 发布:unity3d jpg 编辑:程序博客网 时间:2024/05/16 08:50

题目大意

    一群奶牛彼此之间的族系关系构成了一棵二叉树,构成的过程为:每只奶牛要么不生,要么生两只奶牛。将这样一棵族系关系二叉树称作这群奶牛的族谱,显然一群奶牛可能有很多种族谱。    这些族谱二叉树有N个节点,且具有如下性质:        1、每个节点的度为0或2,对应为节点奶牛孩子的数目。        2、树的高度等于K,高度是从根到最远的那个叶子所需    要经过的结点数,叶子是指没有孩子的节点。    那么一共有多少种族谱?输出可能的家谱树的个数除以9901的余数。

输入格式

    line 1: 两个由空格分开的整数:N K;

输出格式

    line 1:一个整数,表示可能的家谱树的个数除以9901的余数。

样例输入

5 3

样例输出

2

题解

    以样例为例,节点数为5,高度为3,且满足题目条件的二叉树只有以下两种:     @                                 @    / \                               / \   @   @            和               @   @  / \                                   / \ @   @                                 @   @     经过尝试,感觉以这道题的数据量是不可能搜索所有可能情况然后在输出的。所以树的种数应该是满足某种递推关系,然后采用动态规划的办法算出来的。     那么怎样构成一棵满足要求的树便是关键了。我解题的时候先采用一棵节点为N-1的树和一个节点来构成一棵节点为N的树,然后失败了。。。。后来采用比较大众的思路,一棵树由根节点和它的左右子树构成。如果树的节点数为N,左子树的节点为i,那么右子树节点为N-i-1;同时若数的高度为K,那么左右子树的高度一定不能超过K-1,并且至少有一个为K-1;     由此递推关系就来了:一棵节点数为N,高度为K的树的总可能数为以下三种情况之和:     1、左子树深度为K-1 ,右子树深度小于K-1;     2、右子树深度为K-1,左子树深度小于K-1;     3、左右子树深度都为K-1;    (当然左右子树的节点数是从1到N-2变化的)     在实际实现过程中,我的解法陷入了一个困境,就是当为可能1,2时,深度小于K-1的数的个数需要累加出来,同时还要考虑节点数的可能性。造成代码很冗长,而且会有奇异解。经过一两天的思考,决定参考一下标程。发现标程中非常厉害的引入了一个smalltree数组,将深度小于K-1的树的种数也套在动态规划里递推出来了。     用table[i][j]表示深度为i、节点数为j的树的个数。用另一个数组smalltrees[i-2][j]记录所有深度小于i-1的树,而不仅仅是深度为i-2的树,则有:     table[i][j] := smalltrees[i-2][k]*table[i-1][j-1-k];              // 左子树深度小于i-1,右子树深度为i-1    table[i][j] := table[i-1][k]*smalltrees[i-2][j-1-k];              // 左子树深度为i-1,右子树深度小于i-1    table[i][j] := table[i-1][k]*table[i-1][j-1-k];              // 左右子树深度都为i-1 

代码

#include<stdio.h>int N=0,K=0;int trees[210][210]={0};int strees[210][210]={0};int main(){    int n,i,k,v,w,c;    scanf("%d %d",&N,&K);    trees[1][1]=1;    trees[2][3]=1;    for(k=3;k<=K;k++)        for(n=5;n<=N;n=n+2)        {            /*for(v=1;v<=n-2;v=v+2)                {                    strees[k-2][v]=strees[k-3][v]+trees[k-2][v];                    strees[k-2][v]=strees[k-2][v]%9901;                }*/        for(v=1;v<=n-2;v=v+2)//这步与上一步等效        {            strees[k-2][v]=0;            for(w=1;w<=k-2;w++)                {                    strees[k-2][v]=strees[k-2][v]+trees[w][v];                    strees[k-2][v]=strees[k-2][v]%9901;                }        }            for(i=1;i<=n-1;i=i+2)            {                c=2;                if(n-1-i==i)                    c=1;                trees[k][n]=2*trees[k-1][n-1-i]*strees[k-2][i]+trees[k-1][n-1-i]*trees[k-1][i]+trees[k][n];                trees[k][n]=trees[k][n]%9901;            }        }    printf("%d\n",trees[K][N]);    return 0;}
原创粉丝点击