1.問題描述:
給定乙個正整數n和k
1.> 將n劃分成若干正整數之和的劃分數。
2.> 將n劃分成k個正整數之和的劃分數。
3.> 將n劃分成最大數不超過k的劃分數。
4.> 將n劃分成若干奇正整數之和的劃分數。
5.> 將n劃分成若干不同整數之和的劃分數。
2.問題分類:總的來說這些都是揹包問題;
第乙個問:就是乙個完全揹包,揹包有 1 --- n 種,第 i 種揹包的重量為 i ,價值為 i ;這很好解決:
dp[0] = 1;
for (i = 1;i <= n;i++)
for (j = i;j <= n;j++)
dp[j] += dp[j-i];
其中 dp[j] 是用前 i 個數能構成 j 的種類數,則結果就為 dp[n]
看完這個問題了,那麼 第3個問就知道了 , 即用前 k 種揹包來裝 所得結果,只需把第一層迴圈的 i <= n 改為 i <= k 即可;
dp[0] = 1;
for (i = 1;i <= k;i++)
for (j = i;j <= n;j++)
dp[j] += dp[j-i];
結果同樣為 dp[n] ;
那麼第四個問呢,想想是奇數,那麼 i = 2,4,6,…… 等等值就不能取了,因為這些揹包種類不合要求,這很簡單啊
i++ 改為 i += 2 不就行了;
dp[0] = 1;
for (i = 1;i <= n;i+=2)
for (j = i;j <= n;j++)
dp[j] += dp[j-i];
結果同樣為 dp[n] ;
再看看第五個問,若干個不同的???想到了什麼,就是一種揹包最多只能用一次???這是什麼,經典的 01揹包 啊,與第乙個問的不同就是第二層迴圈的順序而已;
dp[0] = 1;
for (i = 1;i <= n;i++)
for (j = n;j >= i ;j--)
dp[j] += dp[j-i];
最後我們來思考第二個問:
要求只要 k 個,這怎麼辦呢???想想特殊情況…… 如果 k = 1 呢,只能是 n 咯,若果 n = 0 呢, 結果只能是 0 中可能啊,那同樣n < k 的話,不可能分啊 結果為 0 ,好,特殊的考慮完了,那麼我們再考慮,分的結果中有沒有 1 , 如果有 那麼就把剩下的 n - 1 分成 k - 1 份 , 如果沒有呢,那麼我們先拿出 k 份 給每一堆 乙個1, 再把剩下的 n - k 分成 k 份就行了啊,好了,至此,遞迴方法出來了:
int work(int n,int k)
--------------------------------
總結:揹包問題是基礎啊~~~
解題報告 整數劃分
整數劃分 sum.pas c cpp 題目描述 從檔案中讀入乙個正整數n 10 n 31 000 要求將n寫成若干個正整數之和,並且使這些正整數的乘積最大。例如,n 13,則當n表示為4 3 3 3 或2 2 3 3 3 時,乘積 108為最大。輸入格式 sum.in 乙個整數,n 輸出格式 sum...
CSP2019 劃分 解題報告
csp2019 劃分 有乙個長度為 n 的序列 a i n le 4 times 10 7 求 sum a i 2 sum a i 2 dots sum 1 a i 2 的最小值.結論 上述式子能取到最小值,當且僅當最後一塊 即 sum 1 a i 取到了最小值.證明 暫時不會.那我們就 dp 保證...
CSP2019 劃分 解題報告
csp2019 劃分 有 n 個非負整數 a i n le 4 10 7 將它們分為若干部分,記為 s i 要求 s ge s i 設 res sum s i 2 求 res 的最小值 考場上寫的做法.設 f i j 為第一段的起點為 i 終點為 j 時 res 的最小值.樸素做法直接列舉 i,j,...