Expressions UVA - 10157(组合数学+递推)

Expressions UVA - 10157

题目:

给你n个括号,求合法的匹配中,深度不超过d的组合数。

分析:

组合,计数,dp,大整数。

这个题目很像卡特兰数,不过深度有限制,可以利用卡特兰数的递推公式求解;

设DP(k,d)为k对括号形成深度不超过d的合法匹配方法数;则有:

DP(k,d)= Σ(DP(i,d-1)*DP(k-1-i,d)) { i 取0到 k-1 }

(按卡特兰数递推,k对括号分成两组,左边i个生成串A,右边k-1-i个生成串B,

还有一对在A外,形成(A)B形式;这时A的深度最大为d-1,B的深度最大为d)

因此,深度为d的方案数为:DP(k,d)- DP(k,d-1)。


code:

import java.math.BigInteger;
import java.util.Scanner;
public class Main {
	static Scanner cin = new Scanner(System.in);
	static BigInteger[][] f = new BigInteger[151][151];
	static boolean[][] vis = new boolean[151][151];
	
	static BigInteger DP(int n,int d) {
		if(vis[n][d]) 
			return f[n][d];
		vis[n][d] = true;
		if(n <= 1 || d <= 1)
			return f[n][d] = BigInteger.ONE;
		f[n][d] = BigInteger.ZERO;
		for(int i = 0; i < n; i++) 
			f[n][d] = f[n][d].add(DP(i,d-1).multiply(DP(n-i-1,d)));
		return f[n][d];
	}
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        for(int i = 0; i < 151; i++) {
        	f[i][0] = f[i][1] = f[0][i] = f[1][i] = BigInteger.ONE;
        	for(int j = 0; j < 151; j++) {
        		vis[i][j] = false;
        	}
        }
        while(cin.hasNext()) {
        	int n = cin.nextInt();
        	int d = cin.nextInt();
        	if(n <= 2 || d <= 1) {
        		System.out.println("1");
        		continue;
        	} 
        	n >>= 1;
        	DP(n,d);
        	DP(n,d-1);
        	System.out.println(f[n][d].subtract(f[n][d-1]));
        }
    }

}

你可能感兴趣的:(#,组合数学,#,Java)