數的劃分---動態規劃

題目描述 Description

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

1 5 1

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

輸入描述 Input Description

輸入:n,k (6<n<=200,2<=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;}

 

我是參考討論區裏的一位大神的解法做出來的

下面貼出這個解法

這一題實際上是組合數學裏面的經典問題,跟第二類Stirling數有些相似。可以把一個數值爲n的數看成n個小球,

劃分的份數k看作是k個盒子,那麼本題的要求就是:

將n個小球放到k個盒子中,小球之間與盒子之間沒有區別,並且最後的結果不允許空盒

與第二類Stirling數的遞推公式的推導過程相似:

將n個小球放到k個盒子中的情況總數 =

1. 至少有一個盒子只有一個小球的情況數

+

2. 沒有一個盒子只有一個小球的情況數



這樣進行劃分的原因是這種分類足夠特殊,1和2都有可以寫出來的表達式:

1. 因爲盒子不加區分,那麼1的情況數與“將n-1個小球放到k-1個盒子中”的情況數一樣

2. 沒有一個盒子只有一個小球,那麼把每個盒子中拿出來一個小球,對應的是“把(n-k)個小球放到k個盒子中的情況數

至於1和2中的兩種等價關係爲什麼成立,可以用集合A=集合B的方式去證明



最後將上面的敘述轉化爲dp的表達形式:

f[n][k]代表將n個小球放到k個盒子中且沒有空盒的情況,那麼

f[n][k] = f[n-1][k-1] + f[n-k][k]

轉化成代碼即可

 

#include<stdio.h>
int f[205][10];
int main(){
	int n, k, i, j;
	scanf("%d%d", &n, &k);
	for (i = 1; i <= n; i++)
		f[i][1] = 1;

	f[0][0] = 1;
	for (i = 1; i <= n; i++){
		for (j = 1; j <= k && j <= i; j++){
			f[i][j] = f[i - 1][j - 1] + f[i - j][j];
		}
	}
	printf("%d\n", f[n][k]);
	return 0;
}

歡迎關注公衆號「後知後jue」,微信搜索關注回覆「1024」,你懂的!

 

 

 

發佈了77 篇原創文章 · 獲贊 71 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章