您的位置:首页 > 其它

ZJU 2604 Little Brackets - 动态规划 Catalan数变形

2008-10-16 20:42 483 查看
题目描述:

定义一个括号序列的Depth为最深的嵌套层数。问n对括号,depth为k的括号序列共有多少种。

分析:

很类似Catalan数的题目。回忆经典的Catalan数:f
表示n对括号能够组成多少种不同的序列。那么可以得出f
的递推式:

f
=∑f[i]*f[n-i-1](0<=i<n)


对于此题可以用类似的思路得到递推式。

设f[i][j]表示i对括号能组成多少个depth为j的的序列。那么初始条件为f[0][0]=f[1][1]=1。考虑f[i][j],设与第一个前括号配对的后括号之间有k对括号(如下图),那么可以把f[i][j]分为两个子问题:括号里的k对括号,和括号后面的i-k-1对括号。

( ..[k对括号].. ) ..[i-k-1对括号]..

那么可以写出以下递推式:

f[i][j] = ∑ ( f[k][j-1]*g[i-k-1][j-1] + g[k][j-1]*f[i-k-1][j] ) ,(0<=k<i),其中g[i][j]=∑f[i][k](0<=k<=j)。

显然最后数字很大,需要大数

/*

ZJU2604 Little Brackets

*/

#include <stdio.h>

#include <string.h>

#define clr(a) memset(a,0,sizeof(a))

#define cpy(a,b) memcpy(a,b,sizeof(b))

#define N 51

/****************************************************/

#define DIGIT 4 //一个数组元素存放的位数个数

#define DEPTH 10000 //DEPTH = 10DIGIT

#define MAX 500 //数组的长度

typedef int bignum_t[MAX+1];

//赋值

void value(bignum_t a,const char val[]){ //val为数字字符串

char buf[MAX*DIGIT+1],ch;

int i,j;

memset((void*)a,0,sizeof(bignum_t));

memcpy(buf,val,sizeof(val));

for (a[0]=strlen(buf),i=a[0]/2-1;i>=0;i--)

ch=buf[i],buf[i]=buf[a[0]-1-i],buf[a[0]-1-i]=ch;

for (a[0]=(a[0]+DIGIT-1)/DIGIT,j=strlen(buf);j<a[0]*DIGIT;buf[j++]='0');

for (i=1;i<=a[0];i++)

for (a[i]=0,j=0;j<DIGIT;j++)

a[i]=a[i]*10+buf[i*DIGIT-1-j]-'0';

for (;!a[a[0]]&&a[0]>1;a[0]--);

}

//输出

void Write(const bignum_t a){

int i,j;

for (printf("%d",a[i=a[0]]),i--;i;i--)

for (j=DEPTH/10;j;j/=10)

printf("%d",a[i]/j%10);

puts("");

}

//加法

void add(bignum_t a,const bignum_t b){//高精度数a+b,结果在a中

int i;

for (i=1;i<=b[0];i++)

if ((a[i]+=b[i])>=DEPTH) a[i]-=DEPTH,a[i+1]++;

if (b[0]>=a[0]) a[0]=b[0];

else

for (;a[i]>=DEPTH&&i<a[0];a[i]-=DEPTH,i++,a[i]++);

a[0]+=(a[a[0]+1]>0);

}

//大数乘大数

void mul(bignum_t c,const bignum_t a,const bignum_t b){//高精度数a*b,结果在c中

int i,j;

memset((void*)c,0,sizeof(bignum_t));

for (c[0]=a[0]+b[0]-1,i=1;i<=a[0];i++)

for (j=1;j<=b[0];j++)

if ((c[i+j-1]+=a[i]*b[j])>=DEPTH)

c[i+j]+=c[i+j-1]/DEPTH,c[i+j-1]%=DEPTH;

for (c[0]+=(c[c[0]+1]>0);!c[c[0]]&&c[0]>1;c[0]--);

}

/**************************************************/

bignum_t f

;

bignum_t g

;

bignum_t x,y;

#define G(a,b) ((a)<(b)?(g[a][a]):(g[a][b]))

int main()

{

int i,j,k,n,m,T=0;

for(i=0;i<N;i++) for(j=0;j<N;j++){

value(f[i][j],"0"); value(g[i][j],"0");

}

//DP

value(f[0][0],"1"); value(f[1][1],"1");

value(g[0][0],"1"); value(g[1][1],"1");

for(i=2;i<N;i++) for(j=1;j<=i;j++){

for(k=0;k<i;k++){

mul(x,f[k][j-1],G(i-k-1,j-1));

mul(y,G(k,j-1),f[i-k-1][j]);

add(x,y);

add(f[i][j],x);

}

cpy(g[i][j],g[i][j-1]);

add(g[i][j],f[i][j]);

}

//input

while(scanf("%d%d",&n,&m),n+m){

if(T) puts("");

printf("Case %d: ",++T);

Write(f
[m]);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: