【剑指offer❤️】14.剪绳子

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

一 用动态规划

通常是用来求最优解(最大值,最小值)
从上到下分析, 从下到上实现
什么时候可以用动态规划:
(1)大问题分解为小问题,如果小问题的最优解组合起来 ==大问题的最优解
(2)整体问题的最优解依赖于各个子问题的最优解
(3)大问题分解为小问题,这些小问题还有相互重叠的更小子问题(之前的青蛙)

java:

class Solution {
    public int maxProductAfterCutting(int length)
    {
        int n=length;
        if(n<2)
            return 0;
        if(n==2)
            return 1;
        if(n==3)
            return 2;
        int[] p = new int[n+1];
        p[0]=0;
        p[1]=1;
        p[2]=2;
        p[3]=3;
        
        int max=0;
        int pro=0;
        for(int i = 4;i<=n;i++){
            max=0;
            for(int j =1;j<=i/2;j++){
                pro=p[j]*p[i-j];
                if(max < pro)
                    max = pro;
                p[i] = max;
            }
        }
        
        max = p[n];
        return max;
        
    }
}

C++:

class Solution {
public:
    int maxProductAfterCutting(int length) {
        if(length <2)
            return 0;
        if(length==2)
            return 1;        
        if(length==3)
            return 2;
            
        int *p = new int[length+1];
        p[0]=0;
        p[1]=1;
        p[2]=2;
        p[3]=3;
        int max=0;
        int pro=0;
        for(int i=4;i<=length;i++){
            max = 0; //新的 i 重新开始 算max
            for(int j=1;j<=i/2;j++){
                pro = p[j]*p[i-j];
                if(max < pro)
                    max = pro;
                p[i] =max;
            }
        }
        max = p[length];
        delete[] p;
        
        return max;
        
        
    }
};

二 用贪心算法:

在每一步都做出贪婪选择,为什么这样的贪婪选择会得到最优解,需要用数学方式证明贪婪选择是正确的。

java:

class Solution {
    public int maxProductAfterCutting(int length)
    {
                int n=length;
                if(n<2)
                    return 0;
                if(n==2)
                    return 1;
                if(n==3)
                    return 2;
                
                int obj3= n-((n/3)*3)==1? n/3-1 : n/3;
                int obj2 = (n-obj3*3)/2;
                
                return (int)Math.pow(3,obj3) * (int)Math.pow(2,obj2);
                
                
    }
}

C++:

class Solution {
public:
    int maxProductAfterCutting(int length) {
            int n=length;
            if(n<2)
                return 0;
            if(n==2)
                return 1;
            if(n==3)
                return 2;
            
            int obj3=n/3;
            if((n-obj3*3)==1)  //最后的余数要是4的话,最优解是2*2=4 > 1*3=3
                --obj3;        //所以得把最后的那个3 变成 4
            int obj2=(n-obj3*3)/2;
            
            return (int)(pow(3,obj3)) * (int)(pow(2,obj2));
    }
};

猜你喜欢

转载自blog.csdn.net/beauman/article/details/89599951