【noi 2.6_9281】技能树(DP)

题意:要求二叉树中每个节点的子节点数为0或2,求有N个节点高度为M的不同的二叉树有多少个(输出 mod 9901 后的结果)。

解法:f[i][j]表示高度为i的有j个节点的二叉树个数。同上题一样,把高度为i的树分解成1个根节点和2棵子树,子树中有一棵高度为i-1,较高,枚举其结点数,另一颗较矮,高度为0~i-2(用sum存),结点数也可知道了。分别左子树和右子树较高,便*2。还有2子树一样高,同为i-1时的情况。
==》也可转化为一棵高i-1,另一棵高0~i-1,*2后减去多算的两子树同高 i-1 的情况。

注意——循环可限制大小时,不要轻易缩小该循环范围。因为缩小后没有提到的那几个状态要想清楚后另外赋值。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6 #define N 310
 7 #define M 110
 8 #define mod 9901
 9 
10 int f[M][N],sum[N][M];
11 int main()
12 {
13     int n,m;
14     scanf("%d%d",&n,&m);
15     f[1][1]=sum[1][1]=1;
16     for (int j=2;j<=n;j++)
17       f[1][j]=sum[1][j]=0;
18     for (int i=2;i<=m;i++)
19     {
20       for (int j=1;j<=n;j++)
21       {
22         f[i][j]=0;
23         for (int k=1;k<j;k++)
24           f[i][j]=(f[i][j]+(2*f[i-1][k]*sum[i-1][j-k-1]-f[i-1][k]*f[i-1][j-k-1])%mod)%mod;
25         sum[i][j]=(sum[i-1][j]+f[i][j])%mod;
26       }
27     }
28     printf("%d\n",f[m][n]);
29     return 0;
30 }

 

posted @ 2016-10-26 09:32  konjac蒟蒻  阅读(859)  评论(0编辑  收藏  举报