您的位置:首页 > 其它

POJ 2084 Game of Connection DP

2010-10-13 21:26 337 查看
dp题,f
=f[0]*f[n-1]+f[1]*f[n-2]+...+f[n-1]*f[0]

设读入数据为n,则有2n个点排成圈,取一个点作为基点(标为0),线段的一点固定在该点,另一点沿顺时针开始,取每一个满足条件的点,即从它顺时针方向的第一个点(标为1)开始,第3,5……2n-1号点都满足条件,每次满足条件时,都将这个圈分为较小的两个部分,将两个部分看成两个子问题,将它们的结果相乘,再把每次满足条件时相乘得到的结果相加即可

看了DISCUS后,发现这个f
是有来历的,是组合数学中的卡特兰数

f[0]=f[1]=1

f
=((4*n-2)/(n+1))*f[n-1]

或者f
=C(2n,n)/(n+1),C(2n,n)为组合数

(N个节点能构成f
个不同的二叉树)

还有,这道题需要用到高精度。。。一开始没察觉,WA了。。。到DISCUSS里找测试数据的时候发现别人说要用高精度

代码:

#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 101
struct BigNum
{
int len;
int d[MAX*2];
}f[MAX];
//char str1[MAX],str2[MAX];
BigNum mul(BigNum &a,BigNum &b)
{
BigNum c;
memset(c.d,0,sizeof(c.d));
int i,j;
for(i=0;i<a.len;i++)
for(j=0;j<b.len;j++)
{
c.d[i+j]+=a.d[i]*b.d[j];
}
for(i=0;i<MAX*2;i++)
if(c.d[i]>10)
{
c.d[i+1]+=c.d[i]/10;
c.d[i]%=10;
}
for(i=MAX*2-1;c.d[i]==0;i--);
c.len=i+1;
return c;
}
BigNum plus(BigNum &a,BigNum &b)
{
BigNum c;
int i,len;
memset(c.d,0,sizeof(c.d));
len=a.len>b.len?a.len:b.len;
for(i=0;i<len;i++)
{
c.d[i]+=a.d[i]+b.d[i];
if(c.d[i]>9)
{
c.d[i]-=10;
c.d[i+1]++;
}
}
if(c.d[len])
len++;
c.len=len;
return c;
}
int main()
{
BigNum t;
int i,j,n;
f[0].len=f[1].len=1;
f[0].d[0]=f[1].d[0]=1;
for(i=2;i<=100;i++)
for(j=0;j<i;j++)
{
t=mul(f[j],f[i-1-j]);
f[i]=plus(f[i],t);
//f[i]+=f[j]*f[i-1-j];
}
while(scanf("%d",&n)!=EOF&&n>0)
{
for(i=f
.len-1;i>=0;i--)
cout<<f
.d[i];
cout<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: