zoukankan      html  css  js  c++  java
  • 算法和数据操作-动态规划与贪婪算法

    动态规划是热门话题,如果一个面试题就问题的最优解,通常是最大值和最小值,而且能分解成若干个子问题,子问题也能分解更小的子问题,就能考虑动态规划

    线分析要能否把大问题分解成小问题,小问题存在最优解,然后把小问题组合起来能够得到整个问题的最优解,用动态规划

    为了避免重复求子问题,可以用从下往上的顺序计算子问题的最优解并存储下来,以此为基础球的最大问题的最优解,从上往下分析问题,从下往上求解问题

    在用动态规划的时候,每一步都可能面临若干选择

    动态规划四个特点:

    1.求一个问题的最优解

    2.整体问题的最优解依赖于各个子问题的最优解

    3.大问题可以分解为若干个小问题,小问题之间还有更小的子问题

    4.从上往下分析问题,从下往上求解问题

    贪婪算法和动态规划算法不一样,应用贪婪算法的时候,每一步都可以做出一个贪婪选择,基于这个选择得到最优解

    面试题14.剪绳子

    题目:给你一根长度为n的绳子,请把绳子剪成n段(m,n都是整数,n>1,m>1),每段绳子的长度记为k[0],k[1],……k[m],请问k[0]*k[1]*……k[m]可能的最大成绩是多少?例如当绳子的长度未8,我们把他剪成长度为2,3,3的3段,此时得到的最大乘积为18

    常规时间O(n^2),空间O(n)-》动态规划

    时间空间都为O(1)的贪婪算法

    动态规划方法

    定义f(n)为把长度为n的绳子剪成若干段后各段长度乘积的最大值

    在剪第一刀的时候,我们有n-1种可能,也就时间出来的第一段绳子的可能长度为1,2,……n-1。因此f(n)=max(f(i)*f(n-1)),其中0<i<n

    这是一个从上到下的递归公式,会有重复子问题,大量不必要的计算,更好的办法是从下到上

    当绳子长度为2的时候,只能剪成长度都为1的两段,因此f(2)等于1,当绳子长度为3的时候,可能把绳子剪成长度分别为1和2的两端或者长度都为1的三段,由于1*2>1*1*1,因此f(3)=2

    public static int maxProductAfterCutting_solution1(int length){
        if(length==1){
            return 0;
        }
        else if(length==2){
            return 1;
        }
        else 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];
        return max;
    }

    贪婪算法

    长度剩下5以上,尽可能多剪长度为3的绳子,长度为4的时候,尽量剪长度为2的绳子

    public static int maxProductAfterCutting_solution2(int length){
        if(length<2){
            return 0;
        }
        else if(length==2){
            return 1;
        }
        else if(length==3){
            return 2;
        }
        int timesOf3=length/3;
        if(length-timesOf3*3==1){
            timesOf3=timesOf3-1;
        }
        int timesOf2=(length-timesOf3*3)/2;
        return (int)(pow(3,timesOf3))*(int)(pow(2,timesOf2));
    }

    在n>=5的时候,可以证明2(n-2)>n并且3(n-3)>n,当绳子长度大于等于5,我们把他剪成长度为3或者2的绳子段。另外当n>=5时,3(n-3)>=2(n-2)因此我们尽可能减去长度为3的段

    当绳子长度为4的时候,剪一刀,2*2>3*1

  • 相关阅读:
    cf854B Maxim Buys an Apartment
    Snuke's Coloring 2-1
    P1087 FBI树
    Card Game for Three
    Many Formulas
    排队
    苹果消消乐(尺取法)
    猴子选大王(约瑟夫)
    进制转化
    UIProgress控件的属性和方法
  • 原文地址:https://www.cnblogs.com/ak918xp/p/14453654.html
Copyright © 2011-2022 走看看