剑指Offer——JZ67.剪绳子【DP | 贪心】

题目传送门


剑指Offer——JZ67.剪绳子【DP | 贪心】_第1张图片


题解

动态规划:

  • 对于任意 n n n,分解为 f 1 , f 2 , f 3 . . . f k f_1,f_2,f_3 ... f_k f1,f2,f3...fk。对于任意 f i , i ∈ [ 1 , k ] f_i,i∈[1, k] fi,i[1,k] 继续拆分后,最后都是乘积关系,所以满足无后效性,可以使用动态规划解决。
  • d p [ i ] dp[i] dp[i] 为长度为 i i i 的绳子分解最大值。
  • 那么状态转移方程: d p [ i ] = m a x ( d p [ i ] , d p [ i − j ] ∗ d p [ j ] ) , d ∈ [ 1 , i / 2 ] dp[i] = max(dp[i], dp[i-j] * dp[j]), d∈[1, i/2] dp[i]=max(dp[i],dp[ij]dp[j]),d[1,i/2]

贪心:

  • 其实很好发现:
    • n < = 3 n <=3 n<=3 的时候,不拆分是最好的,
    • n = = 4 n==4 n==4 的时候,拆分|不拆分是一样的,
    • n > = 5 n >= 5 n>=5 的时候,拆分是最好的。
  • 那么也就是说,最后一定会拆分的结果一定是小于等于 4 4 4 的。
  • 对于 4 4 4,一定是拆分为 2 ∗ 2 2*2 22 是最优解。
  • 那么最后就是在 2 2 2 3 3 3 中选择。
  • n > = 5 n>=5 n>=5 时, 3 ∗ ( n − 3 ) > = 2 ∗ ( n − 2 ) 3*(n-3)>=2*(n-2) 3(n3)>=2(n2),那么就尽可能的按 3 3 3 分割。
  • 最后剩下的如果是 2 2 2,就直接乘进去,如果是 1 1 1,那就取出一个 3 3 3 组成 2 ∗ 2 2*2 22

AC-Code

DP:

class Solution {
public:
    int cutRope(int number) {
        if(number < 2)    return 0;
        if(number == 2)    return 1;
        if(number == 3)    return 2;
        int *dp = new int[number + 1];
        memset(dp, 0, sizeof(dp));
        dp[1] = 1;    dp[2] = 2;    dp[3] = 3;
        for(int i = 4; i <= number; ++i) 
            for(int j = 1; j <= i / 2; ++j) 
                dp[i] = max(dp[i], dp[i - j] * dp[j]);
        int ans = dp[number];
        delete[] dp;
        return ans;
    }
};

贪心:

class Solution {
public:
    int cutRope(int number) {
        if(number < 2)    return 0;
        if(number == 2)    return 1;
        if(number == 3)    return 2;
        return number % 3 == 1 ? pow(3 , (number/3 - 1)) * 4 : pow(3, (number / 3)) * 2;
    }
};

你可能感兴趣的:(剑指Offer)