dp演算法 poj 4119 複雜的整數劃分問題

2022-05-27 01:21:09 字數 2325 閱讀 4924

總時間限制: 200ms 記憶體限制: 65536kb

描述將正整數n 表示成一系列正整數之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 ,k>=1 。

正整數n 的這種表示稱為正整數n 的劃分。

輸入標準的輸入包含若干組測試資料。每組測試資料是一行輸入資料,包括兩個整數n 和 k。

(0 < n <= 50, 0 < k <= n)

輸出對於每組測試資料,輸出以下三行資料:

第一行: n劃分成k個正整數之和的劃分數目

第二行: n劃分成若干個不同正整數之和的劃分數目

第三行: n劃分成若干個奇正整數之和的劃分數目

樣例輸入

5 2樣例輸出23

3提示第一行: 4+1, 3+2,

第二行: 5,4+1,3+2

第三行: 5,1+1+3, 1+1+1+1+1+1

這個問題比之前的整數劃分問題多了乙個限制條件k,可以把這個問題模擬為揹包問題,問題轉化為如下:

從[1...n]中選擇k個數,其和為n,並且選數可以重複,這是個典型的動態規劃問題。

那麼考慮子問題,從[1...i]中選q個數,其和為j.

令f[i][j][q] 表示子問題的解。

下面考慮邊界條件:從[1...1]中選擇1 個數,其和為1,選法唯一 f[1][1][1] = 1;

接下來考慮狀態轉移:

f[i][j][q] = f[i-1][j][q] + f[i][j - i][q - 1]

f[i-1][j][q]表示第i個數不選,那麼要從前i-1個數中選q個,其和為j

f[i][j - i][q-1]表示第i個數選,那麼從前i個數中選q-1個,其和為j-i,這裡i不取i-1是因為在子問題中還會用到i,即每個數選擇不唯一,

這是區別於一般揹包問題的特殊情況。

這樣,解這道題使用三位陣列來記錄動態規劃過程就可以了,但是有些動態規劃是可以使用滾動陣列來節省空間,這道就可以。

那麼假設乙個二位陣列f[j][q],用一層迴圈表示從前i個數中選擇,在第i次迴圈開始執行前,f[j][q]表示從前i-1個數中選q個湊成j,對於f[i][j - i][q-1]

因為在f[i][j][q]之前遍歷到,所以f[j-i][q-1]中的值是第i次迴圈更新過的值,這樣一來,狀態轉移就可以簡化為:

f[j][q] += f[j-i][q-1]

這部分**如下:

dp[0][0] = 1;

for (int i = 1; i <= n; i++)

for (int j = i; j <= n; j++)

for (int q = k; q >= 1; q--)

dp[j][q] += dp[j - i][q - 1];

printf("%d\n", dp[n][k]);

第二問比之前簡單的整數劃分問題增加了數字不能重複的限制,這表現在狀態轉移方程裡邊就是:

設f[i][j]表示從前i個數中湊j,

狀態轉移方程為:

f[i][j] = f[i-1][j-i] + f[i-1][j]

同樣,可以用滾動陣列將二維轉化為一維,注意j要從大到小遍歷

**:

dp1[0] = 1;

for (int i = 1; i <= n; i++)

for (int j = n; j >= i; j--)

dp1[j] += dp1[j - i];

printf("%d\n", dp1[n]);

第三問比簡單的整數劃分問題增加了只能選擇正奇數,注意,數字還是可以重複的,這個其實在弄懂了前兩個題之後就很好寫了

直接寫出狀態轉移方程:

f[i][j] = f[i][j - i] + f[i-2][j]

f[1][1] = 1

用滾動陣列的話,i取奇數遍歷,j需要從小到大遍歷。

**:

dp2[0] = 1;

for (int i = 1; i <= n; i += 2)

for (int j = i; j <= n; j++)

dp2[j] += dp2[j - i];

printf("%d\n", dp2[n]);

整道題**:

#include#include#include#includeusing namespace std;

typedef long long ll;

const int n = 50 + 5;

int dp[n][n], dp1[n], dp2[n];

int main()

return 0;

}

**參考:

4119 複雜的整數劃分問題

總時間限制 200ms 記憶體限制 65536kb 描述將正整數n 表示成一系列正整數之和,n n1 n2 nk,其中n1 n2 nk 1 k 1 正整數n 的這種表示稱為正整數n 的劃分。輸入標準的輸入包含若干組測試資料。每組測試資料是一行輸入資料,包括兩個整數n 和 k。0 n 50,0 k n...

複雜的整數劃分問題 百練4119

將正整數n 表示成一系列正整數之和,n n1 n2 nk,其中n1 n2 nk 1 k 1 正整數n 的這種表示稱為正整數n 的劃分。input 標準的輸入包含若干組測試資料。每組測試資料是一行輸入資料,包括兩個整數n 和 k。0 n 50,0 k n output 對於每組測試資料,輸出以下三行資...

OpenJudge 015 複雜的整數劃分問題

總時間限制 200ms 記憶體限制 65536kb 描述 將正整數n 表示成一系列正整數之和,n n1 n2 nk,其中n1 n2 nk 1 k 1 正整數n 的這種表示稱為正整數n 的劃分。輸入 標準的輸入包含若干組測試資料。每組測試資料是一行輸入資料,包括兩個整數n 和 k。0 n 50,0 k...