zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Delphi中的操作技巧
    C#的排序算法以及随机产生不重复数字的几个Demo
    使用jquery弹窗动态选择脚本示例
    利用override多态原理实现对相似页面的后台代码的抽象,并实现动态GridView动态列数据绑定
    使用VS2010开发一个简单的自定义字段类型
    C#语言使用多态(接口与override) ——帮您剔除对面向对象多态性的疑惑
    探讨复杂linq之group by 和 join
    感悟从java到.NET开发快速入门总结
    使用控制台调试SharePoint出现的一些问题的解决方案
    论欧洲列强争霸霸主——欧洲杯冠军猜想
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5993096.html
Copyright © 2011-2022 走看看