zoj 2711 Regular Words DP,“高维的” 卡特兰数 (8-H)

题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2711

题解:1记录num[i][j][k]   表示从第一个字符开始,长度为i+j+k的,A的个数为i,B的个数为j,C的个数为k的字符串的个数。  

则如果i>=j>=k  则可以根据最后一个字符是A, B还是C,分三类计数,假设是最后一位是A,由于题目的要求是前缀 ,所以前面的放法数恰好是num[i-1][j-1][k]

另外两种情况同理,加的时候注意下标小于零就不要了

             2一开始把所有的元素赋值为0,这样在三重for 中,根本没有将不满足ijk 不等关系的量作为左值。  

             3之所以可以这么算,是因为计算到i,j,k时需要的数据一定在之前算过了~


              (这里只是把这个三维矩阵求了一个转置,不影响最后的结果num[n][n][[n])  

import java.math.*;
import java.util.*;
import java.io.*;
public class Main {
	  
	


	    public static void main(String[] args) throws Exception {
		
	    	 
	        BigInteger [][][] num=new BigInteger [65][65][65];
	        
	         for(int i=0;i<65;i++)
	        	 for(int j=0;j<65;j++)
	        		 for(int k=0;k<65;k++)
	        			    num[i][j][k]=BigInteger.ZERO;
	         
	        num[0][0][0]=BigInteger.ONE;
	         for(int i=0;i<65;i++)
	        	 for(int j=i;j<65;j++)
	        		 for(int k=j;k<65;k++)
	        		    
	        			 {
	        			   if(i>0)num[i][j][k]= num[i][j][k].add(num[i-1][j][k]);
	        			   if(j>0)num[i][j][k]= num[i][j][k].add(num[i][j-1][k]);
	        			   if(k>0)num[i][j][k]= num[i][j][k].add(num[i][j][k-1]);
	        			 }
	             
	         
	           Scanner cin=new Scanner(System.in);
	             while(cin.hasNext())
	             {  
	            	 int n=cin.nextInt();
	                 System.out.println(num[n][n][n]);
	                 System.out.println();
	             }
		      
	    }
	  
	   
	    
}


联想到括号匹配问题,长度为2n的字符串,有n个 “(” , 有n个“)” ,那么合法的式子(可以满足括号匹配)一共有多少?    答案就是 c(2n,n)-c(2n,n-1)=c(2n,n)/(n+1) =h(n)就是卡特兰数 ,也可以按照本题的思想来求   (当然要用高精度,下面写的到最后就溢出了)


#include<iostream>
using namespace std;
typedef long long inta;


int main()
{

  inta f[50][50];

  for(int i=0;i<50;i++)
    for(int j=0;j<50;j++)
         f[i][j]=0;

  f[0][0]=1;

  for(int i=0;i<50;i++)
    for(int j=0;j<=i;j++)
      {
        if(i>0) f[i][j]+=f[i-1][j];
        if(j>0) f[i][j]+=f[i][j-1];
      }

   for(int i=0;i<50;i++)
     cout<<f[i][i]<<endl;
}



posted @ 2013-07-31 16:52  814jingqi  阅读(286)  评论(0编辑  收藏  举报