剪绳子(CutRope) Java动态规划入门分析三

前言

我是想通过一些例题分析来带领我和大家入动态规划的门,若是我哪里分析或思考的有误区,或者错误,请大家能够对我进行评论或私信指正
1.使用最小花费爬楼梯(Min Cost Climbing Stairs) Java动态规划入门分析一
2.打家劫舍(House Robber)Java动态规划入门分析二
3.剪绳子(CutRope) Java动态规划入门分析三

题干

给定一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]* k[1] * … *k[m]可能的最大乘积是多少?
示例1:
输入:8
输出:18
解释:当绳子的长度是8时,可以把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

动态规划入门分析

首先我们先做分析,当绳子长度分别为1,2,3的时候,1无法分割,2[1*1],3[1*2]只能分割为带1的乘积的,此时的分割没有意义(一是因为分割后的值,比本身都小,二是因为带有1,1没有意义),所以我们在以后的分割中不考虑有1的情况(比如例子中8可分割为1*7,这个值不做考虑),分割中有1的情况,没有意义,又因为从4开始可以分割出不带1的分割(2*2),所以我们的基础值应该为2,3,也就是说其他所有的数都可以用2,3组成,然后我们又应该分析状态转移方程:f(0) = 2,f(1) = 3,也就是说n = 4的时候,f(n-2) = f(2)等于4的最大值2*2 = f(0) * f(0),当n = 5的时候f(3) =Math.max(2*3 = f(0)f(1)) ,我们观察发现2*2 ,2*3 的规律为i n - i,所以状态转移方程f(n-2) = Math.max(f(i-2)*f(n-i-2)) {i为正整数,i > 1 && i < n - 1}

代码一

public static int cutRope(int length) {
        if (length < 2) {
            return 0;
        }
        if (length == 2) {
            return 1;
        }
        if (length == 3) {
            return 2;
        }
        int max = 0;
        int res[] = new int[length];
        res[0] = 2;
        res[1] = 3;
        for (int i = 4; i <= length; i++) {
            max = 0;
            for (int j = 2; j <= i / 2; j++) {
                int r = res[j - 2] * res[i - j - 2];
                if (max < r) {
                    max = r;
                    res[i - 2] = max;
                }
            }
        }
        max = res[length-2] ;
        return max;
    }

分析二

上面的分析得到了f(n-2) = Math.max(f(i-2)*f(n-i-2)) {i为正整数,i > 1 && i < n - 1},我们发现这个方程式有个共同点,他们都减去了2,此时我们是否可以这样?f(n) = Math.max(f(i)*f(n-i)) {i为正整数,i > 0 && i < n },这样的话,f(2) = 2, f(3) = 3,f(0),f(1)任意取值(也就是占个位置)

代码二

public static int cutRope(int length) {  
        if(length < 2 ) {
            return 0;
        }
        if(length == 2) {
            return 1;
        }
        if(length == 3) {
            return 2;
        }
        int[] res = new int[length+1];
        //任意赋值res[0],res[1]
        res[0] = 0;
        res[1] = 1;
        res[2] = 2;
        res[3] = 3;
        int max = 0;
        for(int i = 4 ; i <= length ; i ++) {
            max = 0;
            for(int j = 1 ; j <= i/2 ; j++) {  
                int r = res[j] * res[i-j];
                if(max < r) {
                    max = r;
                    res[i] =max;
                }
            }   
        }
        max = res[length];
        return max; 
    }

若是哪里有理解错误的或写错的地方,望各位读者评论或者私信指正,不胜感激。

你可能感兴趣的:(算法练习)