整数拆分!
思路
確定dp數組(dp table)以及下標的含義
dp[i]:分拆數字i,可以得到的最大乘積為dp[i]。
確定遞推公式
可以想 dp[i]最大乘積是怎么得到的呢?
其實可以從1遍歷j,然后有兩種渠道得到dp[i].
一個是j * (i - j) 直接相乘。
一個是j * dp[i - j],相當于是拆分(i - j),對這個拆分不理解的話,可以回想dp數組的定義。
j不用拆分是因為j是從1開始遍歷,拆分j的情況,在遍歷j的過程中其實都計算過了。那么從1遍歷j,比較(i - j) * j和dp[i - j] * j 取最大的。遞推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
也可以這么理解,j * (i - j) 是單純的把整數拆分為兩個數相乘,而j * dp[i - j]是拆分成兩個以及兩個以上的個數相乘。
dp的初始化
嚴格從dp[i]的定義來說,dp[0] dp[1] 就不應該初始化,也就是沒有意義的數值。
這里我只初始化dp[2] = 1,從dp[i]的定義來說,拆分數字2,得到的最大乘積是1
確定遍歷順序
確定遍歷順序,先來看看遞歸公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
dp[i] 是依靠 dp[i - j]的狀態,所以遍歷i一定是從前向后遍歷,先有dp[i - j]再有dp[i]。
枚舉j的時候,是從1開始的。i是從3開始,這樣dp[i - j]就是dp[2]正好可以通過我們初始化的數值求出來。
所以遍歷順序為:
for (int i = 3; i <= n ; i++) {for (int j = 1; j < i - 1; j++) {dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));} }舉例推導dp數組
舉例當n為10 的時候,dp數組里的數值,如下:
總結