dp + 组合数 Codeforces Beta Round #9 (Div. 2 Only) D

http://codeforces.com/problemset/problem/9/D

题目大意:给你一个二叉树和n个数字,满足左小右大,能形成多少种不同的二叉树

思路:定义dp[i][j]表示目前有i个节点,根节点为i,深度为j。

然后我们就暴力枚举顶点i,然后以他为树根,再暴力一下左右两个子树就好了。

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha
")
const int maxn = 35 + 5;
int n, H;
LL dp[maxn][maxn];
/*
定义dp[i][j]表示目前结点,深度为j
dp[i][j] = sigma(dp[i - k - 1][j - z - 1] * dp[k][z]);
*/

int main(){
    cin >> n >> H;
    for (int i = 0; i <= n; i++) dp[0][i] = 1;
    for (int i = 1; i <= n; i++){
        for (int h = 1; h <= i; h++){///目前i个组成的最大层数
            for (int j = 0; j < i; j++){///left的个数
                for (int l = 0; l <= j; l++){///left的最大层数
                    for (int r = 0; r <= i - j - 1; r++){///右边的最大层数
                        if (1 + max(l, r) == h){
                            dp[i][h] += dp[j][l] * dp[i - j - 1][r];
                        }
                    }
                }
            }
        }
    }
    LL ans = 0;
    for (int i = H; i <= n; i++)
        ans += dp[n][i];
    printf("%lld
", ans);
    return 0;
}
View Code

不过我貌似看到了卿学姐写的更加简单,定义的也更加简单

http://www.cnblogs.com/qscqesze/p/5414271.html

定义dp[i][j]表示目前深度小于等于i,有j个节点的所有二叉树的种类数,然后容斥一下就好了

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha
")
const int maxn = 35 + 5;
int n, H;
LL dp[maxn][maxn];
/*
定义dp[i][j]表示目前深度小于等于i,有j个节点的所有二叉树的种类数
dp[i][j] = sigma(dp[i - 1][j - k - 1] * dp[i - 1][j - k]);
*/

int main(){
    cin >> n >> H;
    for (int i = 0; i <= n; i++) {///目前深度为i
        dp[i][0] = 1;
        for (int j = 1; j <= n; j++){///总节点数
            for (int k = 0; k < j; k++){///左边节点的个数
                dp[i][j] += dp[i - 1][k] * dp[i - 1][j - k - 1];
            }
        }
    }
    printf("%lld
", dp[n][n] - dp[H - 1][n]);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/heimao5027/p/5993096.html