• UVA 10312


    题目链接:10312 - Expression Bracketing

    题意:有n个x,要求分括号,推断非二叉表达式的个数。
    思路:二叉表达式的计算方法就等于是Catalan数的,那么仅仅要计算出总数,用总数减去二叉表达式个数。得到的就是非二叉表达式的个数。

    那么计算方法是什么呢。

    看题目中的图,对于n = 4的情况,能够分为这几种情况来讨论:
    四个1。 一个2两个1,一个3一个1。一个4。相应的情况数为1。3。 2。 1。
    答案为f(1)^4 + 3 * f(2) * f(1)^2 + f(3) * f(1) + f(4)。
    一种做法是把n去分解然后计算。可是显然这是不可行的,n最大为26,情况数太多了。
    然后找题解,发现这个竟然有公式,这个式子叫SuperCatalan数。

    然后也有递推出来的解。设dp[n][2]。n表示还有n个子节点未分配。2表示0为最多分配n - 1个点,1为最多分配n个点,这样能保证子树都至少有两个节点。这样就是总情况了,直接用记忆化搜下去就可以

    代码:

    公式解:

    #include <stdio.h>
    #include <string.h>
    
    int n;
    long long Catalan[30], SuperCatalan[30];
    
    int main() {
    	Catalan[1] = Catalan[2] = 1;
    	for (int i = 3; i <= 26; i++) {
    		Catalan[i] = Catalan[i - 1] * (4 * i - 6) / i;
     	}
     	SuperCatalan[1] = SuperCatalan[2] = 1;
     	for (int i = 3; i <= 26; i++) {
    		SuperCatalan[i] = (3 * (2 * i - 3) * SuperCatalan[i - 1] - (i - 3) * SuperCatalan[i - 2]) / i;
    	}
    	while (~scanf("%d", &n)) {
    		printf("%lld
    ", SuperCatalan[n] - Catalan[n]);
     	}
    	return 0;
    }

    递推解:

    #include <stdio.h>
    #include <string.h>
    
    int n;
    long long Catalan[30], dp[30][2];
    
    long long dfs(int n, int flag) {
    	long long &ans = dp[n][flag];
    	if (~ans) return ans;
    	if (n <= 1) return ans = 1;
    	ans = 0;
    	for (int i = 1; i < n + flag; i++)
    		ans += dfs(i, 0) *	dfs(n - i, 1);
    	return ans;
    }
    
    int main() {
    	Catalan[1] = Catalan[2] = 1;
    	for (int i = 3; i <= 26; i++) {
    		Catalan[i] = Catalan[i - 1] * (4 * i - 6) / i;
     	}
    	while (~scanf("%d", &n)) {
    		memset(dp, -1, sizeof(dp));
    		printf("%lld
    ", dfs(n, 0) - Catalan[n]);
     	}
    	return 0;
    }


  • 相关阅读:
    xamarin.Android ImageView 图片圆角(自定义属性、扩展控件)
    Protobuf简介
    创建高性能索引
    缓存表和汇总表
    Schema与数据类型优化
    香农理论在密码学中的应用
    传统密码技术
    自组织神经网络模型与学习算法
    径向基函数神经网络模型与学习算法
    BP神经网络模型与学习算法
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5182150.html
Copyright © 2020-2023  润新知