題目連接:http://codevs.cn/problem/1039/
題目描述 Description
將整數n分紅k份,且每份不能爲空,任意兩種劃分方案不能相同(不考慮順序)。
例如:n=7,k=3,下面三種劃分方案被認爲是相同的。
1 1 5
1 5 1
5 1 1
問有多少種不一樣的分法。html
輸入描述 Input Description
輸入:n,k (6<n<=200,2<=k<=6)
輸出描述 Output Description
輸出:一個整數,即不一樣的分法。
樣例輸入 Sample Input
7 3
樣例輸出 Sample Output
4
輸入輸出樣例說明:四種分法爲:1,1,5;1,2,4;1,3,3;2,2,3; ios
算法分析:
本題相似於放蘋果這道題。 可是放蘋果這道題能夠有盤子爲空,這裏不容許某一份是空的。因此,這裏討論時以拆分結果是否包含1爲主要的討論點。算法
另一定要注意區分簡單的整數劃分這道題。那道題是把n拆分爲若干個正整數之和,個數不限制。這裏限制拆分爲k個。ide
設f(n,k)爲整數n拆分紅k個數字的方案數,則能夠分如下兩種狀況討論。
(1)拆分的結果不包含1的狀況:若是不包含1,咱們把n拆分紅k塊時能夠看作先將每一塊加上個1,則n還剩餘n-k,即f(n-k,k)
(2)拆分的結果包含1的狀況:那麼就直接選一個1,即f(n-1,k-1)。測試
那麼總遞推式爲 f(n,k)=f(n-k,k)+f(n-1,k-1)
這裏還要判斷遞歸終止狀況:
(1)n=0或n<k或k=0時,方案數爲0。(其實k每次最多減小1,總會遇到k==1的狀況,因此k==0能夠忽略。但考慮到可能輸入特殊測試樣例的狀況,能夠保留該條件.)
(2)k=1或k=n時方案數爲 1。spa
1 #include<stdio.h> 2 3 int fun(int n,int k) 4 { 5 if(n==0||n<k||k==0)return 0; 6 else if(n==k||k==1) return 1; 7 else return fun(n-k,k)+fun(n-1,k-1); 8 } 9 10 int main() 11 { 12 int n,k; 13 scanf("%d%d",&n,&k); 14 printf("%d\n",fun(n,k)); 15 }
如下代碼參考:http://blog.csdn.net/noip123/article/details/54782826.net
1 #include<cstdio> 2 using namespace std; 3 int n,k,d[205][8]; 4 int main() 5 { 6 scanf("%d%d",&n,&k); ///把n整數劃分紅k份 7 d[0][0]=1; //邊界 8 for(int i=1;i<=n;i++) 9 for(int j=1;j<=i&&j<=k;j++) //劃分次數不能超過數自己,也不能超過求的劃分次數 10 d[i][j]=d[i-1][j-1]+d[i-j][j]; //遞推計算 11 printf("%d\n",d[n][k]); 12 return 0; 13 }
1 #include<iostream> 2 using namespace std; 3 int dfs(int n,int k) //把n整數劃分紅k份 4 { 5 if(n==0||n<k||k==0)return 0; //沒法繼續劃分 6 if(k==1||n==k)return 1; //只能劃分紅一項 7 return dfs(n-1,k-1)+dfs(n-k,k); 8 } 9 int main() 10 { 11 int n,k; //把n整數劃分紅k份 12 cin>>n>>k; 13 int x=dfs(n,k); 14 cout<<x<<"\n"; 15 return 0; 16 }