總時間限制: 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...