棧是常用的一種資料結構,有n個元素在棧頂端一側等待進棧,棧頂端另一側是出棧序列。你已經知道棧的操作有兩種:push和pop,前者是將乙個元素進棧,後者是將棧頂元素彈出。現在要使用這兩種操作,由乙個操作序列可以得到一系列的輸出序列。請你程式設計求出對於給定的n,計算並輸出由運算元序列1,2,…,n,經過一系列操作可能得到的輸出序列總數。
乙個整數n(1<=n<=15)
乙個整數,即可能輸出序列的總數目。
3
棧是一種常見的資料結構,有許多關於棧的問題,其中之一就是統計元素可能的出棧序列。具體說,就是給定n個元素,依次通過乙個棧,求可能的出棧序列的個數。5
如果我們用直接模擬的方法,當n較大時會很費時間;另一種方法是利用組合數學求出棧序列個數,得到公式
看資料結構,看到棧的時候,發現1個元素進棧,有1種出棧順序;2個元素進棧,有2種出棧順序;3個元素進棧,有5種出棧順序,那麼乙個很自然地問題就是n個元素進棧,共有多少種出棧順序?說來慚愧,以前學資料結構的時候竟然沒有考慮過這個問題。最近在看動態規劃,所以「子問題」這3個字一直在我腦中徘徊,於是解決這個問題的時候我也是用類似「子問題」的方法,說白了就是遞推公式。
我們把n個元素的出棧個數的記為f(n), 那麼對於1,2,3, 我們很容易得出: f(1) = 1 //即 1
f(2) = 2 //即 12、21
f(3) = 5 //即 123、132、213、321、231
然後我們來考慮f(4), 我們給4個元素編號為a,b,c,d, 那麼考慮:元素a只可能出現在1號位置,2號位置,3號位置和4號位置(很容易理解,一共就4個位置,比如abcd,元素a就在1號位置)。
分析:1) 如果元素a在1號位置,那麼只可能a進棧,馬上出棧,此時還剩元素b、c、d等待操作,就是子問題f(3);
2) 如果元素a在2號位置,那麼一定有乙個元素比a先出棧,即有f(1)種可能順序(只能是b),還剩c、d,即f(2),根據乘法原理,一共的順序個數為f(1) * f(2);
3) 如果元素a在3號位置,那麼一定有兩個元素比1先出棧,即有f(2)種可能順序(只能是b、c),還剩d,即f(1),根據乘法原理,一共的順序個數為f(2) * f(1);
4) 如果元素a在4號位置,那麼一定是a先進棧,最後出棧,那麼元素b、c、d的出棧順序即是此小問題的解,即f(3);
結合所有情況,即f(4) = f(3) + f(2) * f(1) + f(1) * f(2) + f(3);
為了規整化,我們定義f(0) = 1;於是f(4)可以重新寫為:
f(4) = f(0)*f(3) + f(1)*f(2) + f(2) * f(1) + f(3)*f(0)
然後我們推廣到n,推廣思路和n=4時完全一樣,於是我們可以得到:
f(n) = f(0)*f(n-1) + f(1)*f(n-2) + ... + f(n-1)*f(0)
即
但這只是乙個遞推公式(若程式設計實現,需要維護乙個一維陣列,時間複雜度為o(n^2))。怎麼把它轉化為通項公式呢,複雜度僅為o(1)?
於是上網搜尋一下,原來真的有這麼乙個公式:c(2n,n)/(n+1) (c(2n,n)表示2n裡取n),並且有個名字叫catalan數。附上wiki的鏈結,寫得太詳細了:
注意資料溢位問題。適當在做乘法的過程中做下除法
#includeusing namespace std;
long long int f(int n)
long long int fs(int a,int b)
int main()
{ int n;
while(~scanf("%d",&n))
{ long long int s1,s2,s;
s1=fs(2*n,n+1)/f(n);
s2=fs(2*n,n+2)/f(n-1) ;
s=s1-s2;
cout<
出棧序列統計
問題描述 棧是常用的一種資料結構,有 n令元素在棧頂端一側等待進棧,棧頂端另一側是出棧序列。你已經知道棧的操作有兩 種 push 和pop 前者是將乙個元素進棧,後者是將棧頂元素彈出。現在要使用這兩種操作,由乙個操作序列可以得到一系列的輸出序列。請你程式設計求出對於給定的 n,計算並輸出由運算元序列...
出棧序列統計
棧是一種常見的資料結構,有許多關於棧的問題,其中之一就是統計元素可能的出棧序列。具體說,就是給定n個元素,依次通過乙個棧,求可能的出棧序列的個數。如果我們用直接模擬的方法,當n較大時會很費時間 另一種方法是利用組合數學求出棧序列個數,得到公式 下面我們來看一種圖形化的方法證明這個等式,很容易理解的。...
出棧序列統計
時間限制 1 sec 記憶體限制 128 mb 提交 21 解決 20 提交 狀態 討論版 命題人 外部匯入 棧是常用的一種資料結構,有n令元素在棧頂端一側等待進棧,棧頂端另一側是出棧序列。你已經知道棧的操作有兩 種 push和pop,前者是將乙個元素進棧,後者是將棧頂元素彈出。現在要使用這兩種操作...