1. 程式人生 > >數的劃分(遞迴)

數的劃分(遞迴)

整數劃分是另外的問題:

題目描述 Description

將整數n分成k份,且每份不能為空,任意兩種劃分方案不能相同(不考慮順序)。
例如:n=7,k=3,下面三種劃分方案被認為是相同的。
7=1+1+5
7=1+5+1
7=5+1+1
問有多少種不同的分法。

輸入描述 Input Description

輸入:n,k
(1< =n <= 200,1<= k <= 6)

輸出描述 Output Description

輸出:一個整數,即不同的分法

樣例輸入 Sample Input

7 3

樣例輸出 Sample Output

4

資料範圍及提示 Data Size & Hint

四種分法為:
1+1+5;
1+2+4;
1+3+3;
2+2+3;

解決思路:

設 f(n,m) 為整數 n 拆分成 m 個數字的方案數.
那麼對於每一個情況一定可以分為以下兩種情況,且不重不漏。
1.不選 1 的情況
如果不選擇 1,我們把 n 拆分成 m 塊的情況,可以等價於將每一塊都減去1,然後分為m塊,即 f(n-m,m)
2.選 1 的情況
那麼就是其中一塊肯定有一個 1,然後對n-1分成m-1塊,即 f(n-1,m-1)。

所以總遞推式為 f(n,m)=f(n-m,m)+f(n-1,m-1)

遞迴結束的條件是
1.n=0 或 n

程式碼:

#include<iostream>  
using namespace std;  
int dfs(int n,int k)  //把n整數劃分成k份  
{  
    if(n==0||n<k||k==0)return 0;  //無法繼續劃分  
    if(k==1||n==k)return 1;       //只能劃分成一項  
    return dfs(n-1,k-1)+dfs(n-k,k);  
}  
int main()  
{  
    int n,k;  //把n整數劃分成k份  
    cin>>n>>k;  
    int
x=dfs(n,k); cout<<x<<endl; return 0; }

把所有情況輸出:

程式碼:

#include <iostream>
#include <stdio.h>
using namespace std;
#define Max 100
int parts;
//整數n分成k份,不考慮順序,譬如把3分成2份,1 2 和 2 1 是同一種情況。 統計所有情況
int divideNtoKpart(int n,int k,int start)//n:整數,k:分成k份 start:從start開始分類
{
    if (k==1) {
        return 1;
    }
    int sum=0;
    for (int i=start; i<=n/k; i++) {
        sum = sum + divideNtoKpart(n-i, k-1, i);
    }
    return sum;
}
//統計情況並輸出所有情況
int divideNtoKpartAndPrintAllConditions(int n,int k,int start,int condition[Max],int index)
{       //n:整數,k:分成k份 start:從start開始分類 陣列condition[Max]:儲存分類的情況  index:陣列下標,從0開始
    if (k==1) {
        condition[index]=n;
        for (int m=0; m<parts; m++) {
            cout<<condition[m]<<" ";
        }
        cout<<endl;
        return 1;
    }
    int sum=0;

    for (int i = start; i<=n/k; i++) {
        condition[index]=i;
        sum = sum + divideNtoKpartAndPrintAllConditions(n-i, k-1, i, condition, index+1);
    }
    return sum;
}
int main(int argc, const char * argv[]) {
    // insert code here...

    int n=0,k=0;
    int conditions[Max];
    cout<<"輸入整數n"<<endl;
    cin>>n;
    cout<<"輸入份數k"<<endl;
    cin>>k;
    parts=k;
    cout<<divideNtoKpartAndPrintAllConditions(n, k, 1, conditions, 0)<<"種"<<endl;
    return 0;
}