1. 程式人生 > 其它 >[劍指Offer]:剪繩子(動歸演算法、貪婪演算法)

[劍指Offer]:剪繩子(動歸演算法、貪婪演算法)

技術標籤:劍指offer演算法

文章目錄


題目描述

給你一根長度為n的繩子,請把繩子剪成整數長的m段(m、n都是整數,n>1並且m>1,m<=n),每段繩子的長度記為k[1],…,k[m]。請問k[1]x…xk[m]可能的最大乘積是多少?

在這裡插入圖片描述

示例1:

輸入
8

返回值
18

題目解答

m > 1 表示至少需要剪1刀

動歸思路:

用動態規劃自下而上的計算,先算出n為1、2、3的最大乘積,知道小的以後在去算更大的乘積。比如n為4時候最大的可能只能在1 * 3,2 * 2之間取得;n為5時,只能在f(1)*f(4),f(2)*f(3)之間取得,而f(2)、f(3)、f(4)之前均已經求出。

程式碼實現:

class Solution {
public:
    int cutRope(int num) {
        if(num <= 1) return 0;
        else if(num == 2) return 1;
        else if(num == 3) return 2;
        
        vector<int> v(num+1);
        for(int i = 0; i < 4; ++i) v[i] = i;
        for(int i = 4; i <= num; ++i){
            int
max = 0; for(int j = 1; j <= i/2; ++j){ int tmp = v[j]*v[i-j]; if(tmp > max) max = tmp; v[i] = max; } } return v[num]; } };

貪婪演算法:

當n>=5時,3(n−3)>=2(n−2)且只在n取5時取等號,且它們都大於 n,所以應把繩子剪成儘量多的3,讓剩下的都是2這樣的組合。

書上言盡於此,我想了下如果剪成其它大小的會不會更好。如果剪成4,那麼 4 = 2 × 2 = 2 + 2 就還是和剪成兩個2一樣;如果剪成5,那麼5還能繼續剪,剪成3和2,往後也是一樣。試想更大的數,比如15,得到一段15以後不剪是不可能的,因為前面說了這時候 3 ( n − 3 ) > 2 ( n − 2 ) > n,那麼剪成更小的段,只要不小於5就一定滿足這個就要繼續減,如果比5小,從1~4的情況都想過了,4是不用管的或者剪成兩個2,3就保留,2也保留,1不要出現。

程式碼實現:

class Solution {
public:
    int cutRope(int num) {
        if(num <= 1) return 0;
        else if(num == 2) return 1;
        else if(num == 3) return 2;
        
        int x = num % 3, y = num / 3;
        if(x == 0) return pow(3, y);
        else if(x == 1) return pow(3, y-1)*2*2;
        else return pow(3, y) * x;
    }
};