題目:
給你一根長度爲 n 的繩子,請把繩子剪成整數長度的 m 段(m、n都是整數,n>1並且m>1),
每段繩子的長度記爲 k[0],k[1]...k[m-1] 。請問 k[0]*k[1]*...*k[m-1] 可能的最大乘積是多少?
例如,當繩子的長度是8時,我們把它剪成長度分別爲2、3、3的三段,此時得到的最大乘積是18。
示例 1:
輸入: 2
輸出: 1
解釋: 2 = 1 + 1, 1 × 1 = 1
示例 2:
輸入: 10
輸出: 36
解釋: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示:
2 <= n <= 58
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/jian-sheng-zi-lcof
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
思路:
剪繩子是動態規劃的標準例題,對於這類問題的難點在於,利用循環從小到大求解最優解;
本題使用動態規劃的難點在於:對於n < 3 的情況下,我們需要手動return,因爲:我們需要在dp中存放n = 1234時本身的長度,而不是n = 1、2、3、4時最優解的長度,這樣在n > 3 時,才能求出對應的dp[n]
其原因在於:當n < 4時,我們必須砍一刀,也就是m > 0,而當n >=4 之後,子問題求解時, 可以不砍了;
至於貪心算法,可以用數學公式推導,每次砍3(n > 4);
代碼:
class Solution {
public:
int cuttingRope(int n) {
if(n <= 1)
return 0;
if(n == 2)
return 1;
if(n == 3)
return 2;
vector<int> dp(n+3, 0);
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
int max = 0;
for(int i = 4; i <= n; i++){
for(int j = 1; j <= i/2; j++)
{
if(max < dp[j] * dp[i - j])
max = dp[j] * dp[i - j];
dp[i] = max;
}
// cout << "i = " << i << "dp[i] = " << dp[i] << endl;
}
return dp[n];
}
};