1. 程式人生 > 實用技巧 >求解圓上2N個點的連線問題(卡特蘭數)

求解圓上2N個點的連線問題(卡特蘭數)

題目描述

圓上有 2n 個不同的點, 兩點之間連成直線段, 要求這些線段不能共點. 計算出有 12 個點時共有多少種不同的連線方式. 設計 C 語言函式, int count (int n), 計算並返回圓上有 2n 個點時的連線方式數量.

分析

我們可以使用遞迴的思想來求解這道題.

設 2n 個節點的連線方法種數為 \(F(n)\).

如上圖(這裡取 n = 4), 不妨給所有的點進行編號, 然後我們分析第一個節點, 發現從 1 號節點出發可以分為兩種情況:

  • 第一種: 1 和 2 或者 8 相連, 那麼一共有 \(2 \times F(2 \times 4 - 2)\) 種連法.
  • 第二種: 1 和 3 到 7 號的節點相連. 我們舉個例子, 如果 1 號節點和 4 號相連, 那麼, 這個圓就被分成了左下和右上兩個部分(以黃色線為分割線), 此時有 \(F(2) \times F(4)\)
    種連法. 把所有的情況累加, 一共有 \(\displaystyle\sum_{k = 2}^{4 - 1}F(2k - 2)F(8 - 2k)\) 種連法.

上面的是一個特殊個例, 然後我們推到一般情況的公式就是:

\[F(2n) = 2 \times F(2n - 2) + \sum_{k = 2}^{n - 1}F(2k - 2)F(2n - 2k) \]

其中, \(F(0) = 0, F(1) = 0, F(2) = 1\).

程式碼

C語言實現

#include <stdio.h>
#include <string.h>

/**
 * 求解圓上 2N 個點連線問題
 * @param n 表示 2N, 為偶數
 * @return 結果數
 */
long count(int n)
{
    if (n == 2)
        return 1;

    long dp[n + 1];
    memset(dp, 0, (n + 1) * sizeof(long));

    dp[0] = dp[1] = 0;
    dp[2] = 1;
    for (int i = 4; i <= n; i += 2)
    {
        long sum = 0;
        for (int k = 4; k <= i - 2; k += 2) // 選 4, 6,..., n - 2 的情況
        {
            sum += (dp[k- 2] * dp[i - k]);
        }
        dp[i] = 2 * dp[i - 2] + sum; // 這裡要加上選 1 和 選 n - 1 的情況
    }
    return dp[n];
}

int main() {

    // 列印 9 個測試資料
    for (int i = 2; i < 20; i += 2)
    {
        printf("%d\n", count(i));
    }

    return 0;
}

測試結果:

1
2
5
14
42
132
429
1430
4862

Python實現

# -*- coding: utf-8 -*-
# @File  : CircleCatalan.py
# @Author: 模糊計算士
# @Date  : 2020/11/27

def count(n):
    if n == 2:
        return 1

    dp = [0] * (n + 1)

    dp[0] = dp[1] = 0
    dp[2] = 1
    for i in range(4, n + 1):
        sum = 0
        for k in range(4, i - 2 + 1):
            sum += dp[k - 2] * dp[i - k]
        dp[i] = 2 * dp[i - 2] + sum
        i += 2

    return dp[n]

for i in range(2, 100, 2):
    print(count(i))

測試結果:

1
2
5
14
42
132
429
1430
4862
16796
58786
208012
742900
2674440
9694845
35357670
129644790
477638700
1767263190
6564120420
24466267020
91482563640
343059613650
1289904147324
4861946401452
18367353072152
69533550916004
263747951750360
1002242216651368
3814986502092304
14544636039226909
55534064877048198
212336130412243110
812944042149730764
3116285494907301262
11959798385860453492
45950804324621742364
176733862787006701400
680425371729975800390
2622127042276492108820
10113918591637898134020
39044429911904443959240
150853479205085351660700
583300119592996693088040
2257117854077248073253720
8740328711533173390046320
33868773757191046886429490
131327898242169365477991900
509552245179617138054608572

從這些結果資料來看, 它們正是卡特蘭數.