數的劃分(遞迴)
阿新 • • 發佈:2019-01-27
整數劃分是另外的問題:
題目描述 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;
}