1039 數的劃分

 題目描述 Description

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

1 5 1

5 1 1
問有多少種不同的分法。

輸入描述 Input Description                  輸出描述 Output Description

輸入:n,k (6<n<=200,2<=k<=6)   輸出:一個整數,即不同的分法

樣例輸入 Sample Input                                        樣例輸出 Sample Output

 7 3                                                                       4

數據範圍及提示 Data Size & Hint

 {四種分法爲:1,1,5;1,2,4;1,3,3;2,2,3;}

分類標籤 Tags 

動態規劃   劃分型DP   noip2001Day1T2

代碼 

 
設 f(n,m) 爲整數 n 拆分成 m 個數字的方案數,那麼分以下兩種情況討論。
 
1° 不選 1 的情況如果不選擇 1,我們把 n 拆分成 m 塊時可以看做先將每一塊加上個 1,則 n 還剩餘 n-m,即 f(n-m,m)
 
2° 選 1 的情況那麼就直接選一個 1,即 f(n-1,m-1)。
因爲是遞歸的方法,所以選擇 1 的個數通過迭代下去
那麼總遞推式爲 f(n,m)=f(n-m,m)+f(n-1,m-1)
 
這裏還要判斷兩種情況         1° n=0 或 n<m 或 m=0 時,方案數爲 0。               2° m=1 或 m=n 時方案數爲 1。

DP遞推:
#include<cstdio>
using namespace std;
int n,k,d[205][8];
int main()
{
    scanf("%d%d",&n,&k);  ///把n整數劃分成k份
    d[0][0]=1;            //邊界
    for(int i=1;i<=n;i++)
      for(int j=1;j<=i&&j<=k;j++)  //劃分次數不能超過數本身,也不能超過求的劃分次數
        d[i][j]=d[i-1][j-1]+d[i-j][j];  //遞推計算
    printf("%d\n",d[n][k]);
    return 0;
}

DFS遞歸:

#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<<"\n";
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章