JZ :14 剪繩子-I (動態規劃 or 貪心)

題目:

給你一根長度爲 n 的繩子,請把繩子剪成整數長度的 m 段(m、n都是整數,n>1並且m>1),
每段繩子的長度記爲 k[0],k[1]...k[m-1] 。請問 k[0]*k[1]*...*k[m-1] 可能的最大乘積是多少?
例如,當繩子的長度是8時,我們把它剪成長度分別爲233的三段,此時得到的最大乘積是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];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章