您的位置:首页 > 其它

Section 2.3-nocows

2017-08-25 10:50 204 查看

题目大意

一群奶牛彼此之间的族系关系构成了一棵二叉树,构成的过程为:每只奶牛要么不生,要么生两只奶牛。将这样一棵族系关系二叉树称作这群奶牛的族谱,显然一群奶牛可能有很多种族谱。
这些族谱二叉树有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]
=2*trees[k-1][n-1-i]*strees[k-2][i]+trees[k-1][n-1-i]*trees[k-1][i]+trees[k]
;
trees[k]
=trees[k]
%9901;
}
}
printf("%d\n",trees[K]
);
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  USACO