void-man

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

dp的经典题目怎么那么多呢?我所谓的经典就是简单但是自己怎么就没有想到转移方程的题目啊啊啊!!

这道题给出节点数n,还有数的层数k,问你能组成多少种二叉树

要求是每个节点的孩子数只能是0或者2

设dp[i,j]表示用i个点组成深度最多为j的二叉树的方法数,则:

dp[i,j]=∑(dp[k,j-1]×dp[i-1-k,j-1])(k∈{1..i-2})
边界条件:dp[1,i]=1

我们要求的是深度恰好为K的方法数S,易知S=dp[n,k]-dp[n,k-1]。但需要注意的是,如果每次都取模,最后可能会有dp[n,k]<dp[n,k-1],所以可以用S=(dp[n,k]-dp[n,k-1]+v) mod v

 

实际上就是出现一种情况后把根节点的左右子树的种类分别算出,相乘就是总的种类了,因为左右子树交换后又是一种的嘛

 

/*
ID: xvoid191
LANG: C++
TASK: nocows
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#define N 205
#define MOD 9901
using namespace std;
int dp[N][N],n,k;//
int main()
{
    freopen("nocows.in","r",stdin);
    freopen("nocows.out","w",stdout);
    scanf("%d %d",&n,&k);
    memset(dp,0,sizeof(dp));
    for(int i = 1; i <= k; i++){
        dp[1][i] = 1;
    }
    for(int i = 2; i <= k; i++){
        for(int j = 3; j <= n; j+=2){
            for(int p = 1; p <= j - 2; p+=2){
                dp[j][i]  = (dp[j][i] + dp[p][i - 1] * dp[ j - p - 1][i - 1])%MOD;
            }
        }
    }
    printf("%d\n",(dp[n][k] - dp[n][k-1] + MOD)%MOD);
}

 

posted on 2012-01-30 23:53  void-man  阅读(517)  评论(2)    收藏  举报