動態規劃之n個元素出棧順序種數
阿新 • • 發佈:2019-01-28
- 問題描述
n個元素依次進棧,共有多少種出棧順序? 演算法分析
1個元素進棧,有1種出棧順序;2個元素進棧,有2種出棧順序;3個元素進棧,有5種出棧順序
我們把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)
然後我們推廣到n,推廣思路和n=4時完全一樣,於是我們可以得到:
f(n) = f(0)*f(n-1) + f(1)*f(n-2) + … + f(n-1)*f(0)
即
具體可以搜尋Catalan數程式程式碼
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n;
cin >> n;
int* arr = new int[n+1];
memset(arr, 0, sizeof (int)*(n+1));
arr[0] = 1;
arr[1] = 1;
//遞推關係式
for (int i=2; i<=n; ++i)
{
for (int j=0; j<i; ++j)
{
arr[i] += arr[j] * arr[i-1-j];
}
}
cout << arr[n] << endl;
delete[] arr;
return 0;
}