數的劃分(遞歸)

整數劃分是另外的問題:

題目描述 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章