写下文章来记录下自己学习算法导论的笔记

文章目录

    • 写下文章来记录下自己学习算法导论的笔记
  • 动态规划的目的
  • 设计动态规划算法
  • 钢条切割问题
    • 问题描述
    • 刻画问题结构(建立方程)
    • 递归方程建立
    • 带备忘录的自顶向下法
    • 自底向下的方法
    • 如何保留切割方案
  • 源代码

动态规划的目的

求出最优子结构

设计动态规划算法

1.刻画一个最优解的结构特征

2.递归定义最优解的值

3.计算最优解的值

4.利用计算出的信息构造一个最优解

钢条切割问题

问题描述

​ Serling公司购买长钢条,将其切割为短钢条出售。切割工序本身没有成本支出。公司管理层希望知道最佳的切割方案。
​ 假定我们知道Serling公司出售一段长度为i英寸的钢条的价格为p;(i=1,2,…,单位为美元)。钢条的长度均为整英寸。表1给出了一个价格表的样例。

​ 钢条切割问题是这样的:给定一段长度为n英寸的钢条和一个价格表p;(i=1,2,…,n),求切割钢条方案,使得销售收益r。最大。注意,如果长度为n英寸的钢条的价格pn足够大,最优解可能就是完全不需要切割。

刻画问题结构(建立方程)

递归方程建立

​ 书中的解释有一点绕,其实递归的思路就是,怎么样,切一刀(可以不切),使得当前的钢条的价格最高(所以此处的i的取值范围到了n(右边什么都不切)),由于自顶向下的递归较为好理解,所以我会用这种思路来进行解释。

PS:由于问题中的范围只有1-10,所以默认其他长度的值为0.

​ 我们现在不是要切一刀钢条吗,编程思想:我挨个切一刀,选出其中获益最大的一刀。好了,现在不就有一个问题,也是我有点难绕过来的一个点,那就是我如何保证我这一刀切下来的钢条获益最大,没事,一刀不够,再来几刀,切下来的继续切,最后切到0,或者人为给一个出口,再一步一步返上来。

​ 关于递归的运算量-指数级递增,为啥,重复算了很多遍,看下图

​ 下面来上代码(java)

   class Solution{public int CUT_RUD(int[] p, int n){//n-代表切掉的量if (n == 0) {return 0;}int q=0;for (int i = 1; i <= n; i++) {q=Math.max(q,p[i]+CUT_RUD(p,n-i));}return q;}}

小细节:这个数组p[]-是人为传入的参数,也就是钢条的收益值,需要注意一下下标,会在文末放入完整的代码

带备忘录的自顶向下法

​ 如若其名所示,该方法其实是递归的改进,就是加入了一个数组来减小递归的运算量(先查后算),可以分成两个函数来写,也可以合并到一起,我根据书上的思路来的,结构更加清晰,第一个函数初始化存表r[],第二个函数用来计算,这种结构也方便用来存储切割方法。

//________________________带有备忘录的自顶向下发top-down with memoization,递归形式-先查,再存____________________________________________________
class Solution{public int MEMOIZED_CUT_RUD(int[] p,int n){if (n < 0) {return 0;}int[] r=new int[n+1];//重新声明空间for (int i = 0; i <= n; i++) {r[i]=-9999;}return MEMOIZED_CUT_RUD_AUX(p,n,r);
}
private int MEMOIZED_CUT_RUD_AUX(int[] p,int n,int[] r){//p[]-利润对应的数组,n-所切的数组,r[]放入已计算的数组,当前钢条数能代表的最大利润if(r[n]>=0)return r[n];int q=0;if (n == 0) {//切的长度为0q=0;}else {q = -999;for (int i = 1; i <= n; i++) {q=Math.max(q,p[i]+MEMOIZED_CUT_RUD_AUX(p, n-i, r));}}r[n]=q;return q;
}}

自底向下的方法

​ 思想很简单,从0开始求,一步步累计上去,直到需要求的位。代码比较直接。

​ 稍微有点难理解的就是为什么需要有两个循环,第一个循环-用来表示当前长度的利益最大值(从0开始),第二个循环就是求解子问题(怎样使得每一步的钢条最大化)

public int BOTTOM_UP_CUT_ROD(int[] p,int n){int[] r=new int[n+1];
int q=0;for (int j = 1; j <= n; j++) {q=-9999;for (int i = 1; i <= j; i++) {//max怎么切使得钢条利益最大化q=Math.max(q,p[i]+r[j-i]);}r[j]=q;//用来记录当前长度为j的利益最大值}
return r[n];
}

如何保留切割方案

​ 就是在原有的基础上再增添一个数组,在比较最大值其作用时,传入标号,从程序可以看出来切割方案的保留是从小到大,有一些需要完善的地方就是无法把3段以上保留下来,毕竟是一维数组,不是多维的。

//————————————————————————————将方案也打印出来——————————————————————————————
private Map<String,Integer> EXTENDED_BOTTOM_UP_CUT_ROD(int[] p,int n){Map<String, Integer> map = new HashMap<String, Integer>();int[] r=new int[n+1];//用来记录int[] s=new int[n+1];//用来记录int q=0;for (int j = 1; j <= n; j++) {q=-9999;for (int i = 1; i <= j; i++) {//max怎么切使得钢条利益最大化if (q<(p[i]+r[j-i])){q=p[i]+r[j-i];s[j]=i;}}r[j]=q;//用来记录当前长度为j的利益最大值}map.put("最大收益",r[n]);map.put("切割方案",s[n]);return map;
}
public void PRINT_CUT_ROD_SOLUTION(int[] p,int n){Map<String, Integer> map = EXTENDED_BOTTOM_UP_CUT_ROD(p,n);System.out.println("最大收益:"+map.get("最大收益"));System.out.print("切割方案:");int i=1;while (n>0){if (i==1)System.out.print(map.get("切割方案"));else System.out.print("+"+map.get("切割方案"));n=n-map.get("切割方案");i=0;}
}//________________________带有备忘录的自顶向下发top-down with memoization,递归形式-先查,再存,带切割方案____________________________________________________public int MEMOIZED_CUT_RUD(int[] p,int n){if (n < 0) {return 0;}int[] r=new int[n+1];//重新声明空间int[] s=new int[n+1];for (int i = 0; i <= n; i++) {r[i]=-9999;}return MEMOIZED_CUT_RUD_AUX(p,n,r,s);}private int MEMOIZED_CUT_RUD_AUX(int[] p,int n,int[] r,int[] s){//p[]-利润对应的数组,n-所切的数组,r[]放入以计算的数组if(r[n]>=0)return r[n];int q=0;//重新声明空间if (n == 0) {//切的长度为0q=0;}else {q = -999;for (int i = 1; i <= n; i++) {int t=p[i]+MEMOIZED_CUT_RUD_AUX(p, n-i, r,s);if (q<t){q=t;s[n]=i;}}}for (int i = 0; i <= n; i++) {System.out.print(s[i]);System.out.print("  ");}System.out.println();r[n]=q;return q;}

源代码

//钢条切割问题
//问题描述:钢条切割问题是这样的:给定一段长度为n英寸的钢条和一个价格表p;(i=1,2,…,n),求切割钢条方案,使得销售收益rn最大。
// 注意,如果长度为n英寸的钢条的价格p。足够大,最优解可能就是完全不需要切割。
public class _15_1 {public static void main(String[] args) {Solution v=new Solution();int[] p={0};p=new int[40];p[0]=0;p[1]=1;p[2]=5;p[3]=8;p[4]=9;p[5]=10;p[6]=17;p[7]=17;p[8]=20;p[9]=24;p[10]=30;System.out.println(v.CUT_RUD(p,4));System.out.println(v.MEMOIZED_CUT_RUD(p,11));System.out.println(v.BOTTOM_UP_CUT_ROD(p,4));v.PRINT_CUT_ROD_SOLUTION(p,4);}
}
class Solution{//递归方法调用,递归的思想:将这根钢条切成2半,左半边不去管它,改变右半边的长度,从1-n(右半边钢条n-1-0),// 调用Max函数来递归求得何时才能使得钢条的分割成2半public int CUT_RUD(int[] p, int n){//n-代表切掉的量if (n == 0) {return 0;}int q=0;for (int i = 1; i <= n; i++) {q=Math.max(q,p[i]+CUT_RUD(p,n-i));}return q;}//________________________带有备忘录的自顶向下发top-down with memoization,递归形式-先查,再存____________________________________________________public int MEMOIZED_CUT_RUD(int[] p,int n){if (n < 0) {return 0;}int[] r=new int[n+1];//重新声明空间int[] s=new int[n+1];for (int i = 0; i <= n; i++) {r[i]=-9999;}return MEMOIZED_CUT_RUD_AUX(p,n,r,s);}private int MEMOIZED_CUT_RUD_AUX(int[] p,int n,int[] r,int[] s){//p[]-利润对应的数组,n-所切的数组,r[]放入以计算的数组if(r[n]>=0)return r[n];int q=0;//重新声明空间if (n == 0) {//切的长度为0q=0;}else {q = -999;for (int i = 1; i <= n; i++) {int t=p[i]+MEMOIZED_CUT_RUD_AUX(p, n-i, r,s);if (q<t){q=t;s[n]=i;}}}for (int i = 0; i <= n; i++) {System.out.print(s[i]);System.out.print("  ");}System.out.println();r[n]=q;return q;}//_____________________________________自底向上法_________________________________________________________public int BOTTOM_UP_CUT_ROD(int[] p,int n){int[] r=new int[n+1];int q=0;for (int j = 1; j <= n; j++) {q=-9999;for (int i = 1; i <= j; i++) {//max怎么切使得钢条利益最大化q=Math.max(q,p[i]+r[j-i]);}r[j]=q;//用来记录当前长度为j的利益最大值}return r[n];}//————————————————————————————将方案也打印出来——————————————————————————————private Map<String,Integer> EXTENDED_BOTTOM_UP_CUT_ROD(int[] p,int n){Map<String, Integer> map = new HashMap<String, Integer>();int[] r=new int[n+1];//用来记录int[] s=new int[n+1];//用来记录int q=0;for (int j = 1; j <= n; j++) {q=-9999;for (int i = 1; i <= j; i++) {//max怎么切使得钢条利益最大化if (q<(p[i]+r[j-i])){q=p[i]+r[j-i];s[j]=i;}}r[j]=q;//用来记录当前长度为j的利益最大值}map.put("最大收益",r[n]);map.put("切割方案",s[n]);return map;}public void PRINT_CUT_ROD_SOLUTION(int[] p,int n){Map<String, Integer> map = EXTENDED_BOTTOM_UP_CUT_ROD(p,n);System.out.println("最大收益:"+map.get("最大收益"));System.out.print("切割方案:");int i=1;while (n>0){if (i==1)System.out.print(map.get("切割方案"));else System.out.print("+"+map.get("切割方案"));n=n-map.get("切割方案");i=0;}}
}
"最大收益"));System.out.print("切割方案:");int i=1;while (n>0){if (i==1)System.out.print(map.get("切割方案"));else System.out.print("+"+map.get("切割方案"));n=n-map.get("切割方案");i=0;}}
}

算法导论-动态规划(钢条切割问题)相关推荐

  1. 算法导论 动态规划钢条切割问题 C语言

    动态规划钢条切割问题 动态规划(dynamic programming)与分治法类似.分治策略将问题划分为互不相交的子问题,递归求解子问题,再将子问题进行组合,求解原问题.动态规划应用于子问题重叠的情 ...

  2. 算法导论-动态规划-钢条切割问题

    文章目录 一.钢条切割定义 二.具体步骤 1.思考 2.代码思考 3.动态规划求解 4.伪代码 三:总结: 一.钢条切割定义 图为价格表 给定一段长度是n的钢条和一个价格表,求切割方案使得收益达到最大 ...

  3. 动态规划 — 钢条切割问题

    动态规划: 什么是动态规划? 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息.在求解任一子问题时 ...

  4. 动态规划-钢条切割(java)

    数据结构与算法系列源代码:https://github.com/ThinerZQ/AllAlgorithmInJava 本文源代码:https://github.com/ThinerZQ/AllAlg ...

  5. 动态规划 -- 钢条切割问题

    给定一段长度为n英寸的钢条和一个价格表p,求切割钢条方案(钢条的长度均为整英寸),使得销售收益最大. 我们可以计算出长度为n英寸的钢条共有2的(n-1)次方种不同的切割方案. 为解决规模为n的原问题, ...

  6. 动态规划—钢条切割问题与01背包问题

    目录 1.钢条切割问题 第一种求最优解方案: 第二种求最优解方案: 第一种方法是 带备忘的自顶向下法 第二种方法是 自底向上法 2.01背包问题 1,穷举法(把所有情况列出来,比较得到 总价值最大的情 ...

  7. 算法导论例题——钢管切割

    <算法导论>(CLRS)中第一个dp例题(rodcutting)的C++代码 #include<iostream> #include<vector> #includ ...

  8. 算法导论动态规划切割钢条

    保存已经求得的子问题解 自底向上 #ifndef _MODEL_ #define _MODEL_ #include<vector> #include<map> using st ...

  9. 动态规划——钢条切割

    有一根钢条,和他的长度价格表,真么样切割才能使得售出的钢条收益最大. 不考虑钢条的切割损耗. 输入n 表示钢条的长度 价格表p[i] 表示长度为i的钢条出售的价格 ------------------ ...

最新文章

  1. python拍7游戏代码_Python基础语法-7(小游戏)
  2. 字符串工具类---StringUtils
  3. Linux启动redis提示 /var/run/redis_6379.pid exists, process is already running or crashed
  4. LSGO软件技术团队2015~2016学年第十二周(1116~1122)总结
  5. C 语言程序设计基础不好,想10天考国二C语言程序设计证书,可能吗?
  6. python算法应用(四)——多维缩放
  7. WinAPI: Rectangle - 绘制矩形
  8. 系统编程之文件IO(一)——概述
  9. t450加固态硬盘教程_Thinkpad T450 超级笔记本 开箱更换SSD和内存
  10. 哪个计算机软件可以编辑动画文字,文字动画视频电脑版
  11. Web前端开发常用9个开源框架
  12. 一文搞懂深度学习所有工具——Anaconda、CUDA、cuDNN
  13. openproject_OpenProject入门
  14. 几行代码,把你的小电影全部藏好了!
  15. Raster Map光栅图 VS Vector Map矢量图
  16. 全球跨境电商平台有哪些?中国卖家占多少?
  17. Cesium加载各种互联网地图(一)
  18. 大数据揭秘诺奖评选“潜规则”
  19. FBI变态测试题,猜中一半的,赶紧去看看心理医生哦
  20. 51单片机16×16点阵led屏滚动显示+protues仿真+按键功能(史上最全)

热门文章

  1. 基于Go语言Gin+Xorm的OA办公系统
  2. 100个英语超精简口语短句
  3. python循环3次停止_【Python】quot;为所欲为quot;怎么成语接龙?
  4. 5G+工业互联网应用场景大集锦!
  5. python六大数据类型详解
  6. H2O with R 简明使用手记·上篇
  7. 有奖调研 | 让虚拟照入现实的完美AR开发平台长什么样?
  8. 引入思考的电影电视动漫(二)
  9. 个人日记——用来激励自己
  10. Eclipse多行注释