1039 數的劃分

題目連接: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 }  
DP遞推
 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 }  
DFS遞歸
相關文章
相關標籤/搜索