zoukankan      html  css  js  c++  java
  • 动态规划(一)钢条切割

    简介

    什么是动态规划

    答:动态规划与分治法相似,都是通过组合子问题的解来求解原问题。他们之间的不同是,分治法将问题划分为互不相交的子问题,而动态规划应用于子问题重合的情况。使用分治法求解子问题重合的问题,会做许多不必要的工作,动态规划将已经求解的子问题保存到一张表格中,从而避免了反复求解重合子问题的情况。

    动态规划常用来解决什么问题

    答:最优化问题。最优化问题可以有很多可行解,每个解都有一个值,我们希望寻找具有最优值的解,最大或最小。我们称这样的解是问题的一个最优解(最优解可以有多个)。

    设计动态规划算法的步骤

    1. 刻画一个最优解的结构特征;
    2. 递归的定义最优解;
    3. 计算最优解的值,通常采用自底向上的方法;
    4. 利用计算出的信息构造最优解;

    问题

    分析

    从算法的角度来思考,我们如果要解决一个问题,只需要把这个问题的所有可能都列举出来。通过来检查每一种情况,来计算出一个最优的解。我们如何来穷举出所有的可能呢?

    我们从钢条的最左端开始,在钢条长度为1的位置切割,那么问题的解即是r(n) = p[1] + r(n-1),我们看到问题的规模减小了,我们可以递归的解决子问题r(n-1)。一般的,r(n) = p[i] + r(n-i),i = 1,2,... n。

    代码

    /**
         * 递归解法
         * @param p
         * @param n
         * @return
         */
        public static int cut_rod(int[] p, int n){
            if(n == 0) return 0;
            int q = Integer.MIN_VALUE;
            for (int i = 1; i <= n; i++) {
                q = Math.max(q, p[i] + cut_rod(p, n - i));
            }
            return q;
        }
    

    递归的解法求解了很多不必要的子问题,而我们可以将求解过的子问题记录下来。当遇到子问题时只需从表格中查找,这样就避免买子问题的重复计算。

    /**
         * 带备忘录的自顶向下递归解法
         * @param p
         * @param n
         * @return
         */
        public static int memoized_cut_rod(int[] p, int n){
            int[] r = new int[n + 1];
            for (int i = 0; i < r.length; i++) {
                r[i] = Integer.MIN_VALUE;
            }
            return memoized_cut_rod_aux(p, n, r);
        }
    
        public static int memoized_cut_rod_aux(int[] p, int n, int[] r){
            if(r[n] >= 0) return r[n];
            int q;
            if(n == 0){
                q = 0;
            }else {
                q = Integer.MIN_VALUE;
                for (int i = 1; i <= n; i++) {
                    q = Math.max(q, p[i] + memoized_cut_rod_aux(p, n - i, r));
                }
            }
            r[n] = q;
            return q;
        }
    
    
    
    /**
         * 自底向上的解法
         * @param p
         * @param n
         * @return
         */
        public static int bottom_up_cut_rod(int[] p, int n){
            int[] r = new int[n + 1];
    
            r[0] = 0;
            for (int i = 1; i <= n; i++) {
                int q = Integer.MIN_VALUE;
                for (int j = 1; j <= i; j++) {
                    q = Math.max(q, p[j] + r[i - j]);
                }
                r[i] = q;
            }
    
            return r[n];
        }
    
    奋斗不一定成功,不奋斗一定不会成功!
  • 相关阅读:
    单元测试之NUnit一
    第一个基于ArcGIS的Android应用
    NuGet的安装和使用
    PIE调用Python获得彩色直方图
    PIE调用Python返回得到直方图矩阵数组
    PIE属性表多字段的文本绘制
    微信公众号配置和使用客服消息
    python多线程爬取斗图啦数据
    微信小微商户获取申请状态
    微信小微商户申请入驻
  • 原文地址:https://www.cnblogs.com/xucoding/p/12183253.html
Copyright © 2011-2022 走看看