动态规划和贪婪算法

动态规划:

如果一个问题是求一个问题的最优解(通常是求最大值或者最小值),而且该问题能够分解成若干个子问题,并且问题之间还有重叠的更小的子问题,就可以考虑用动态规划来解决这个问题;

我们在应用动态规划之前要分析能否把大问题分解成小问题,分解后的每个小问题也存在最优解,如果把小问题的最优解组合起来能够得到整个问题的最优解,那么我们就可以用动态规划解决这个问题;

动态规划求解问题的四个特点:
1、求解问题的最优解;
2、整体问题的最优解依赖于各个子问题的最优解;
3、这些小问题之间还有相互重叠的更小的子问题;
4、从上往下分析问题,从下往上求解问题;

贪婪算法:

贪婪和动态规划不一样,当我们应用贪婪算法解决问题的时候,每一步都可以做出一个贪婪选择,基于这个选择,我们确定能够得到最优解(原因要拿数学公式来证明贪婪选择是正确的);

两种算法的代码:

代码1:袋鼠过河问题
代码2:剪绳子

题目描述:给你一段长为n的绳子,请把绳子剪成m段(m、n都是整数,n > 1,m >
1);每段绳子的长度计为k[0],k[1],k[2],,,,,,k[m];请问k[0]×k[1]×k[2]×,,,,,,×k[m]的最大乘积是多少?例如n=8时,剪成2,3,3,长度的三段乘积最大为18;

动态规划:

f(n) = max(f(i)×f(n-i));

贪婪算法:

因为当n≥5时:
2×(n-2) > n;
3×(n-3)>n;
3×(n-3)≥2×(n-2)
所以绳子长度n≥5时:我们要尽可能多的剪长度为3的绳子,当剩下的绳子长度为4时,
把绳子剪为两段长度为2的绳子;

代码:

    /**
     * 动态规划
     * @param length
     * @return
     */
    public static int max_ride(int length) {
        //题目要求至少要剪一刀的
        if(length < 2) {  //小于2时
            return 0;
        }
        if(length == 2) {  //等于2时
            return 1;
        }
        if(length == 3){
            return 2;
        }

        int[] products = new int[length+1];
        products[0] = 0;
        products[1] = 1;
        products[2] = 2;
        products[3] = 3;

        int max = 0;
        for(int i = 4;i <= length;++i) {
            max = 0;
            for(int j = 1;j <= i/2;++j) {
                int product = products[j]*products[i-j];
                if(max < product) {
                    max = product;
                }
                products[i] = max;
            }
        }
        max = products[length];
        products = null;
        return max;
    }

    /**
     * 贪婪算法
     * @param length
     * @return
     */
    public static int max_product(int length) {
        if(length < 2) {  //小于2时
            return 0;
        }
        if(length == 2) {  //等于2时
            return 1;
        }
        if(length == 3){
            return 2;
        }

        int times_3 = length/3;
        if(length-times_3*3 == 1) {
            times_3 -= 1;
        }
        int times_2 = (length-times_3*3)/2;
        return (int)(Math.pow(3,times_3)*(int)(Math.pow(2,times_2)));
    }

测试代码:

public static void main(String[] args) {
        System.out.println(max_ride(5));
        System.out.println(max_product(5));
        System.out.println(max_ride(7));
        System.out.println(max_product(7));
        System.out.println(max_ride(8));
        System.out.println(max_product(8));
        System.out.println(max_ride(12));
        System.out.println(max_product(12));
    }

运行结果:

6
6
12
12
18
18
81
81

猜你喜欢

转载自blog.csdn.net/QQ2899349953/article/details/85330559