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]));
}
}
}