每種劃分方式都是按照從大到小排序的
樣例分析:
5有7種劃分方式
5 = 5
5 = 4 + 1
5 = 3 + 2
5 = 3 + 1 + 1
5 = 2 + 2 + 1
5 = 2 + 1 + 1 + 1
5 = 1 + 1 + 1 + 1 + 1
解法一:用揹包問題的思想
把整數n看做乙個容量為n的揹包
然後一共有n個物品,每個物品的體積分別是1,2,3,...,n。(也就是n這個數的所有因子)
每種物品可以用無限次,所以是完全揹包問題
求恰好裝滿揹包的方案數
狀態表示:
集合:dp[i][j]表示從物品1~i中選,總體積恰好為j的選法的集合
屬性:數量
狀態計算:集合的劃分,同揹包問題
根據第i個物品選了幾個來劃分
狀態數量:n ^ 2
轉移數量:n(粗略估計的,比n小,應該為log n)
時間複雜度:n ^ 3
然後進行優化
二維做法
1 #include 2然後再轉化為一維,再從小到大迴圈體積注意初值問題:求最大值時,當都不選時,價值顯然是 0using
namespace
std;
3const
int n = 1010, mod = 1e9 + 7;4
intdp[n][n];
5int
main()
11for (int i = 1; i <= n; i++) 17}
18}19 cout << dp[n][n] <
20return0;
21 }
而求方案數時,當都不選時,方案數是 1(即前 i 個物品都不選的情況也是一種方案),所以需要初始化為 1
即需要這樣:
for (int i = 0; i <= n; i++)
等價變形後: f[0] = 1
一維做法
1 #include 2解法二: ps : 最小值1 表示 :j個數的總和是i的數中最小的數為1using
namespace
std;
3const
int n = 1010, mod = 1e9 + 7;4
intdp[n];
5int
main() 13}
14 cout << dp[n] <
15return0;
16 }
1 #include 2using
namespace
std;
3const
int n = 1010, mod = 1e9 + 7;4
intdp[n][n];
5int
main() 13}
14int res = 0;15
for (int i = 1; i <= n; i++)
18 cout << res <
19return0;
20 }
NYOJ90 整數劃分(計數DP)
時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 將正整數n表示成一系列正整數之和 n n1 n2 nk,其中n1 n2 nk 1,k 1。正整數n的這種表示稱為正整數n的劃分。求正整數n的不同劃分個數。例如正整數6有如下11種不同的劃分 6 5 1 4 2,4 1 1 3 3...
整數劃分(劃分dp)總結
寫了幾個題發現整數劃分是一類題,而不是一道題。具體題型 1 n相同元素放入m個相同的盤子 盤子允許為空 例題 放蘋果 poj 1664設dp i j 為 j 個元素放入i個盤子轉移方程 dp i j dp i 1 j 新新增乙個盤子,盤子為空 dp i j dp i j i i個盤子 各取出乙個 2...
計數DP 劃分數
蒜頭君特別喜歡數學。今天,蒜頭君突發奇想 如果想要把乙個正整數 n n 分解成不多於 k k 個正整數相加的形式,那麼一共有多少種分解的方式呢?蒜頭君覺得這個問題實在是太難了,於是他想讓你幫幫忙。共一行,包含兩個整數 n 1 leq n leq 300 n 1 n 300 和 k 1 leq k l...