1. 程式人生 > >ACM 【程式=演演算法+資料結構】@蠟筆小軒V

ACM 【程式=演演算法+資料結構】@蠟筆小軒V

偶然看到的題目,居然可以用卡特蘭數解。

12個人排兩排,每排都按身高由小到大排,要求第二排相應位置上每個人的身高都比第一排上的人要高,問有多少種排法?

卡特蘭數的一個模型就是括號匹配。先給括號標號(序號對應身高),我們把左括號當作第一排的人,右括號當作第二排的人。

1

2

3

4

5

6

(

(

)

(

)

)

第一排

1

2

4

第二排

3

5

6

有結論:

  1. 左/右括號的序號遞增(滿足兩排都有序)
  2. 第n個右括號之前必定至少有n左括號(排在第二排某個位置,對應第一排的肯定比其小)

我們可以得出括號匹配可以對應到身高排列。還要證反過來也成立。

先明確這裡身高對應排列序號,合法的括號匹配就是左右括號數量一致(這裡顯然),並且前面的“第n個右括號之前必定至少有n左括號”。

對於每一個滿足要求的身高排列,

a1

<

a2

<

a3

ʌ

ʌ

ʌ

b1

<

<>b2

<

b3

對b1,我們知道身高小於b1的a至少有a1

對於b2,我們知道身高小於b2的a至少有a1,a2

。。。。

我們讓a對應(,b對應),而括號的位置序號對應身高序號。

所以可以證明按身高排序的ai 和bi序列,替換成括號後是合法匹配。

小結一下Catalan數

令h( 0 ) = 1 ,h( 1 )= 1 ,catalan數滿足遞迴式:
  h(n)
=  h( 0 ) * h(n - 1 +  h( 1 ) * h(n - 2 + ... +  h(n - 1 )h( 0 ) (其中n >= 2 )
該遞推關係的解為:
  h(n)
= C(2n,n) / (n  + 1 ) (n = 1 , 2 , 3 , ...)

得到式子:

  1. h(n) =  h( 0 ) * h(n
    - 1 +  h( 1 ) * h(n - 2 + ... +  h(n - 1 )h( 0 )   (其中n >= 2 )
  2. h(n) = C(2n,n) / (n  + 1 )  = C(2n,n)-C(2n, n+1) (n = 1 , 2 , 3 ,...)

式子1對應的模型:

  1. 在圓上選擇2n個點,將這些點成對連線起來,使得所得到的n條線段不相交的方法數。
  2. 將一個凸n+2邊形區域分成三角形區域的方法數
  3. 給定N個節點,能構成多少種形狀不同的二叉樹?(一定是二叉樹 !  先取一個點作為頂點,然後左邊依次可以取0至N - 1個相對應的,右邊是N - 1到0個,兩兩配對相乘
  4. 矩陣鏈乘: P = a1×a2×a3×……×an,依據乘法結合律,不改變其順序,只用括號表示成對的 乘積,試問有幾種括號化的方案?切割成左右兩塊(a1 x a2 ... x ak)( ak+1 x ... x an)因為只有n-1個分割點,所以為 h(n-1)

式子2對應的模型:

先求一道題:n個元素的出棧,入棧合法方案數。

令1表示進棧,0表示出棧,則可轉化為求一個2n 位、含n 個1、n 個0的二進位制數,滿足從左往右掃描到任意一位時,經過的0數不多於1數。顯然含n 個1、n 個0的2n 位二進位制數共有C(2n,n) 個,下面考慮不滿足要求的數目.

考慮一個含n 個1、n 個0的2n位二進位制數,掃描到第2m+1 位上時有m+1 個0和m 個1(容易證明一定存在這樣的情況),則後面的0-1排列中必有n-m 個1和n-m-1 個0。將2m+2 及其以後的部分0變成1、1變成0,則對應一個n+1 個0和n-1 個1的二進位制數。反之亦然(相似的思路證明兩者一一對應)。

從而 C(2n,n) / (n  + 1 )= C(2n,n)-C(2n, n+1) 。證畢。

以這道題為基礎,有

  1. n對括號的匹配問題
  2. n個元素的出棧,入棧合法方案數。
  3. 有2n個人排成一行進入劇場。入場費5元。其中只有n個人有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票,問有多少中方法使得只要有10元的人買票,售票處就有5元的鈔票找零?(將持5元者到達視作將5元入棧,持10元者到達視作使棧中某5元出棧)
  4. 一位大城市的律師在她住所以北n個街區和以東n個街區處工作。每天她走2n個街區去上班。如果她從不穿越(但可以碰到)從家到辦公室的對角線,那麼有多少條可能的道路? (因為有對角線的存在,向上走的次數如果大於向右的次數,會越過對角線)

                                                     

well蛋!

參考了下: http://www.cppblog.com/MiYu/archive/2010/08/07/122573.html