1. 程式人生 > >洛谷P1044 :棧(卡特蘭數)

洛谷P1044 :棧(卡特蘭數)

https://www.luogu.org/problemnew/show/P1044

題目背景

棧是計算機中經典的資料結構,簡單的說,棧就是限制在一端進行插入刪除操作的線性表。

棧有兩種最重要的操作,即pop(從棧頂彈出一個元素)和push(將一個元素進棧)。

棧的重要性不言自明,任何一門資料結構的課程都會介紹棧。寧寧同學在複習棧的基本概念時,想到了一個書上沒有講過的問題,而他自己無法給出答案,所以需要你的幫忙。

題目描述

寧寧考慮的是這樣一個問題:一個運算元序列,1,2,.....n(圖示為1到3的情況),棧A的深度大於n。

現在可以進行兩種操作,

  1. 將一個數,從運算元序列的頭端移到棧的頭端(對應資料結構棧的push操作)

  2. 將一個數,從棧的頭端移到輸出序列的尾端(對應資料結構棧的pop操作)

使用這兩種操作,由一個運算元序列就可以得到一系列的輸出序列,下圖所示為由123生成序列231的過程。

(原始狀態如上圖所示)

你的程式將對給定的n,計算並輸出由運算元序列1,2,…,n經過操作可能得到的輸出序列的總數。

輸入輸出格式

輸入格式:

 

輸入檔案只含一個整數n(1≤n≤18)

 

輸出格式:

 

輸出檔案只有1行,即可能輸出序列的總數目

 

設 x 為當前出棧序列的最後一個,則x有n種取值,因為每一個數都可能最後出棧。

由於x是最後一個出棧的,所以可以將已經出棧的數分成兩部分

  1. 比x小

  2. 比x大

比x小的數有x-1個,所以這些數的全部出棧可能為f[x-1]

比x大的數有n-x個,所以這些數的全部出棧可能為f[n-x]

所以一個x的取值能夠得到的所有可能性為f[x-1] * f[n-x]

另外,由於x有n個取值,所以

ans = f[0]*f[n-1] + f[1]*f[n-2] + ... + f[n-1]*f[0];

這就是所謂的卡特蘭數。

#include<stdio.h>
#define N 20
long long a[N];
int main()
{
    int n,i,j;
    scanf("%d",&n);
    a[0]=1;
    a[1]=1;
    for(i=2;i<=n;i++)
    {
        for(j=0;j<i;j++)
            a[i]+=a[j]*a[i-j-1];
    }
        
    printf("%lld\n",a[n]);
    return 0;
} 

 

題目描述

小和尚每日練武真的是很累啊,但是為了以後更和諧。也沒有辦法了,只能天天那刻苦了;有一日練武結束後去找師傅聊天,猛然間,師傅說到,其實在這個世界上想混的好的話,光武功高是不行的,也要能噴能聊,你們要多讀書了,從此以後小和尚每天都要抽出一部分時間來讀書,有一天看到了一個叫卡特蘭數的東西,看了半天你沒有看懂,只知道是個數列,因此想讓小朋友們幫忙找到數列前邊的一些卡特蘭數;快快幫忙吧;
注: 卡特蘭數遞推關係的解為:
h(n)=C(2n,n)/(n + 1) (n=1,2,3,)

 

輸入

輸入資料有多組,每組資料首先輸入一個整數n(n<=30). 然後有n個正整數m(每個正整數m<50);

 

輸出

對於每個正整數m,輸出相應的卡特蘭數,每個數佔一行;

 

樣例輸入

3
1
2
3

 

樣例輸出

1
2
5
#include<stdio.h>
#define N 35
long long a[N];
int main()
{
	int n,i,j,t;
	a[0]=1;
	a[1]=1;
	for(i=2;i<=30;i++)
	{
		for(j=0;j<i;j++)
			a[i]+=a[j]*a[i-j-1];
	}
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		printf("%lld\n",a[n]);
	}	
	return 0;
}