1. 程式人生 > >10343 劃分凸多邊形(找規律,遞迴&分治,備忘)

10343 劃分凸多邊形(找規律,遞迴&分治,備忘)

10343 劃分凸多邊形

時間限制:800MS  記憶體限制:65535K
提交次數:0 通過次數:0

題型: 程式設計題   語言: C++;C;VC;JAVA

Description

問題描述:一個正凸N邊形,可以用N-3條互不相交的對角線將正N邊形分成N-2個三角形。
現在要求讀入N邊形的N(N≤20),輸出不同劃分方法的總數(要求解的是劃分方法數,而不需要輸出各種劃分法)。

這裡,注意:
(1)頂點編號,認為頂點皆不相同,因此不允許認為將凸N邊形轉置視為相同劃分。
(2)若輸出是“No answer”,請注意大小寫和無標點。

輸入輸出舉例:
輸入: N=3,               輸出:1
輸入: N=5,		輸出:5
輸入: N=2,		輸出:No answer
輸入: N=6,		輸出:14
輸入: N=8,		輸出:132

例如:
當N=5時,共有5種分法。
當N=6時,對六邊形的三角形所有劃分,請看下圖:



輸入格式

N,代表正凸N邊形。


輸出格式

不同劃分方法的總數。


輸入樣例

5


輸出樣例

5


提示

題目所求的是分法總數,並不要求具體的分法。而且,N可以大到21。
因此,用簡單搜尋或列舉會耗時較多,而應該想方設法找出N為不同值時,分法總數的變化規律。

把一個正凸N邊形的各個頂點按照順時針分別編上1,2,……,N。
頂點1,頂點N和頂點I(I∈[2, N-1])能夠構成一個三角形S。
這樣凸N邊形就被分成三部分:一個三角形S、一個I邊形和一個N+1-I邊形(I, N+1-I∈[2, N-1])。
因此,凸N邊形分為三角形總數Total(N)等於I邊形的分法總數乘以N+1-I邊形的分法總數之積,還要在I分別取2,3,……,N-1時都累加起來。

遞推公式如下:
Total(N) = sum{ Total(I)*Total(N+1-I) | for I=2 to N-1}   if N>=4
Total(2) = Total(3) = 1

注意: 2點的多邊形視為蛻化的多邊形,定義其Total(2)=1,是為遞推公式推導用。
但按題目意思當N=2時輸出無解。

另外,此題需要注意的是,如果你寫的純遞迴程式可能會超時的,因為這裡遞迴存在重複,且重複數量龐大。
需要用陣列將你算過的元素儲存下來,避免重複的遞迴計算,這樣優化後,才能通過。


作者

zhengchan

我的實現程式碼

#include <iostream>
#include <cmath>
#include <string.h>

using namespace std;

int *arr;

int Total(int n){
    if (arr[n] != 0) {//有備忘記錄
        return arr[n];
    }
    
    int count = 0;
    for (int i = 2; i < n; i++) {
        
        count += Total(i) * Total(n + 1 -i);
    }
    
    arr[n] = count;//進行到此,記錄此備忘
    
    return count;
}

int main()
{
    int n;
    cin >> n;
    if (n == 2) {//預處理
        cout << "No answer";
    }else{
        arr = new int[n + 1];
        
        memset(arr, 0, (n + 1) * sizeof(int));
        arr[2] = 1;
        arr[3] = 1;
        
        cout << Total(n);
    }
    
    cout << endl;
    return 0;
}