原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1023
参考文章:http://baike.baidu.com/view/2499752.htm?fromId=1163998
http://hi.baidu.com/dybivzbhnucdxzr/item/d48bb01d6c3d644ce65e0607
如百度百科上所说,出栈顺序的可能个数实际上是卡特兰数。
分析:
设f(n)为个数为元素个数n的序列的出栈方式的数量。假设在整个入栈和出栈过程中,第一次出栈的元素次序为k。则k将1~n的元素分为1~k-1,元素个数为k-1,和k+1~n,元素个数为n-k,而k的可能取值为1~n。
若我们把k视为一个确定的序数,那么根据乘法原理,f(n)的问题就等价于f(n)=f(k-1)*f(n-k),k=1~n。所以f(n)=f(0)*f(n-1)+f(1)*f(n-2)+...+f(n-2)*f(1)+f(n-1)*f(1)。当然这实际上是用到了动态规划的思想。
而此题还涉及到一个大数加法和大数乘法的问题,具体见代码。
#include<stdio.h>
#include<string.h>
int res[101][200] = {0};
int temp[200] = {0};
void add(int *x, int *y){
int i, t;
for(i=0; x[i]!=0&&y[i]!=0; i++){
x[i] += y[i] -'0';
}
for(i; y[i]!=0; i++){
x[i] += y[i];
}
for(t=0; x[t]!=0; t++){
if(x[t+1]!=0){
x[t+1] += (x[t]-'0')/10;
}
else{
if((x[t]-'0')/10!=0){
x[t+1] += (x[t]-'0')/10+'0';
}
else{
x[t+1] = 0;
}
}
x[t] = (x[t]-'0')%10+'0';
}
}
int* multiple(int *x, int *y){
int i, j, length;
for(i=0; i<200; i++){
temp[i] = 0;
}
for(i=0; x[i]!=0; i++){
for(j=0; y[j]!=0; j++){
if(temp[i+j]!=0){
temp[i+j] += (x[i]-'0')*(y[j]-'0');
}
else{
temp[i+j] += (x[i]-'0')*(y[j]-'0')+'0';
}
}
}
length = 0;
while(temp[length]!=0){
length++;
}
for(i=0; i<length; i++){
temp[i+1] += (temp[i]-'0')/10;
temp[i] = (temp[i]-'0')%10 + '0';
}
if(temp[length]!=0){
temp[length] += '0';
}
while(temp[length]!=0){
if((temp[length]-'0')/10!=0){
temp[length+1] += temp[length]/10+'0';
}
temp[length] = (temp[length]-'0')%10+'0';
length++;
}
return temp;
}
int main(){
int n, i, j;
res[0][0] = '1';
res[1][0] = '1';
for(i=2; i<=100; i++){
for(j=0; j<i; j++){
add(res[i], multiple(res[j], res[i-j-1]));
}
}
while(scanf("%d", &n) != EOF){
i=199;
while(i>=0){
if(res[n][i] != 0){
printf("%c", res[n][i]);
}
i--;
}
printf("\n");
}
return 0;
}