[剑指Offer]剪绳子

dp

Posted by JinFei on April 6, 2020

题目描述

给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

输入描述

输入一个数n,意义见题面。(2 <= n <= 60) 输入: 8 输出: 18

解题思路

  • dp
  • f(n)的时候,可以切一刀f[i],剩下的f[n - i]
  • 初始化的时候要注意初值问题
  • dp[i] = max(dp[j], dp[i - j]);
class Solution {
public:
    int cuttingRope(int n) {
        vector<int> dp(n + 1, 0);
        if(n < 2){
            return 1;
        }
        if(n == 2){
            return 1;
        }
        if(n == 3){
            return 2;
        }
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;
        int res = 0;
        for(int i = 4; i <= n; i++){
            for(int j = 1; j <= i / 2; j++){
                dp[i] = max(dp[i], dp[j] * dp[i - j]);
            }
        }
        return dp[n];
    }
};

大数溢出的问题

  • 选择最多的3
class Solution {
public:
    int cuttingRope(int n) {
        if(n<=3) return n-1;
        int mod = 1000000007;
        long long res = 1;
        while(n>4){
            res*=3;
            res%=mod;
            n-=3;
        }
        res = res*n%mod;
        return res;
    }
};
class Solution {
public:
    int Rope(int number) {
        if(number <= 0){
            return -1;
        }
        if(number == 1){
            return 1;
        }
        if(number == 2){
            return 1;
        }
        if(number == 3){
            return 2;
        }
        
        int dp[number + 1];
        memset(dp, 0, sizeof(int) * (number + 1));
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 2; // init the dp
        dp[3] = 3;
        int res = 0;
        for(int i = 4; i <= number; i++){
            res = 0;
            for(int j = 1; j <= i / 2; j++){
                if(dp[j] * dp[i - j] > res){
                    res = dp[j] * dp[i - j];
                }
            }
            dp[i] = res;
        }
        return dp[number];
    }
};

0229解题思路

  • dp数组需要先初始化为0

dp[0] = 0; dp[1] = 1; dp[2] = 2; dp[3] = 3; for(int i = 4; i <= n; i++){ for(int j = 1; j < i; j++){ dp[i] = max(dp[i], dp[i - j] * dp[j]) } } return dp[n];