动态规划 -- 钢条切割问题
给定一段长度为n
英寸的钢条和一个价格表p
,求切割钢条方案(钢条的长度均为整英寸),使得销售收益最大。
我们可以计算出长度为n英寸的钢条共有2的(n-1)次方种不同的切割方案。
为解决规模为n的原问题,我们可以这样考虑。先求解形式完全一样,但规模更小的子问题。我们将钢条左边切割下长度为i
的一段(i
的取值范围是[1, n]),然后只对右边剩下的长度为n-i
的一段继续进行切割(递归求解)。即问题的分解方式为:将长度为n
的钢条分解为左边开始一段,以及剩余部分继续分解的结果。这样我们就可以做出如下解答:
function cut_rod(p, n) {if (n == 0) return 0;let sum = -Infinity;for (let i = 1; i <= n; i++) {sum = Math.max(sum, p[i] + cut_rod(p, n - i))}return sum;
}
let p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30];
console.log(cut_rod(p, 5)); //13
然而,以上代码一旦输入规模变大,程序运行时间就会变得相当长。以n=4为例,当我们对整个递归过程展开是,它所做的工作量如下:
回过头看,会发现整个过程进行了大量的重复计算,严重浪费了效率。
接下来展示如何将它转换为一个更高效的动态规划算法。动态规划方法对每个子问题只求解一次,并将结果保存下来。如果随后在此需要此子问题的解,无需重新计算,只需查找保存的结果。有两种方法:
- 带备忘的自顶向下法
此方法仍然按照自然的递归形式编程,但过程中会保存每个子问题的解。
function memorized_cut_rod(p,n){let arr = new Array(n);arr.fill(-1);function _memorized_cut_rod(p, n, arr){if(arr[n] >= 0){return arr[n];}if(n == 0){return 0;}let sum = -Infinity;for (let i = 1; i <= n; i++) {sum = Math.max(sum, p[i] + _memorized_cut_rod(p, n - i, arr))}arr[n] = sum;return sum;}return _memorized_cut_rod(p, n, arr)
}
let p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30];
console.log(memorized_cut_rod(p, 5)); //13
对照之前的代码,动态规划方法付出了额外的内存空间,但是节省了非常多的时间。
- 自底向上法
这种方法一般需要恰当定义子问题“规模”的概念,使得任何子问题的求解都只依赖于“更小的”子问题的求解。
function bottom_up_cut_rod(p, n) {let arr = new Array(n);// 长度为0时的解为0arr[0] = 0;for (let i = 1; i <= n; i++) {let sum = -Infinity;for (let j = 1; j <= i; j++) {// n = 1时,i-j = 0,arr[0]已知为0// n = 2时,i-j = 1、0,arr[1]、arr[0]均已知// n = 3时,i-j = 2、1、0,arr[2]、arr[1]、arr[0]均已知sum = Math.max(sum, p[j] + arr[i - j]);}// 数组中记录子问题的解arr[i] = sum;}return arr[n];
}
let p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30];
console.log(bottom_up_cut_rod(p, 5)); //13
此方法采用子问题的自然顺序,若j < i
,则规模为j
的子问题比规模为i
的子问题更小,因此,过程依次求解规模为i = 0,1,…,n的子问题。
动态规划 -- 钢条切割问题相关推荐
- 动态规划 — 钢条切割问题
动态规划: 什么是动态规划? 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息.在求解任一子问题时 ...
- 算法导论 动态规划钢条切割问题 C语言
动态规划钢条切割问题 动态规划(dynamic programming)与分治法类似.分治策略将问题划分为互不相交的子问题,递归求解子问题,再将子问题进行组合,求解原问题.动态规划应用于子问题重叠的情 ...
- 动态规划—钢条切割问题与01背包问题
目录 1.钢条切割问题 第一种求最优解方案: 第二种求最优解方案: 第一种方法是 带备忘的自顶向下法 第二种方法是 自底向上法 2.01背包问题 1,穷举法(把所有情况列出来,比较得到 总价值最大的情 ...
- 算法导论-动态规划-钢条切割问题
文章目录 一.钢条切割定义 二.具体步骤 1.思考 2.代码思考 3.动态规划求解 4.伪代码 三:总结: 一.钢条切割定义 图为价格表 给定一段长度是n的钢条和一个价格表,求切割方案使得收益达到最大 ...
- 动态规划-钢条切割(java)
数据结构与算法系列源代码:https://github.com/ThinerZQ/AllAlgorithmInJava 本文源代码:https://github.com/ThinerZQ/AllAlg ...
- 动态规划——钢条切割
有一根钢条,和他的长度价格表,真么样切割才能使得售出的钢条收益最大. 不考虑钢条的切割损耗. 输入n 表示钢条的长度 价格表p[i] 表示长度为i的钢条出售的价格 ------------------ ...
- 动态规划-钢条切割问题
int BottomUpCutRod(int p[],int n) { int *r=new int[n+1]; r[0]=0; for (int j=1;j<=n;j++) { int q=- ...
- 《算法导论》中动态规划求解钢条切割问题
动态规划算法概述 动态规划(dynamic programming)1是一种与分治方法很像的方法,都是通过组合子问题的解来求解原问题.不同之处在于,动态规划用于子问题重叠的情况,比如我们学过的斐波那契 ...
- 钢条分割 动态规划java_【动态规划】初识,钢条切割问题
正文之前其实动态规划老早之前就看过, 但是可惜的是印象不深,到今天彻底忘得差不多了,这两天看<算法导论>终于让我啃下了二叉搜索树和红黑树两个家伙,虽然还未曾熟练于胸,但是基本能用了...现 ...
最新文章
- Linux命令find的35个实例
- Git根据文件名字查询修改文件内容
- python入门区块链技术_区块链入门教程
- Dispatch Queue 之 Invoke 当前队列
- 10分钟用python编写贪吃蛇小游戏_牛得一批!10分钟用Python编写一个贪吃蛇小游戏...
- JS面向对象的实现和原理
- mysql报错ERROR 1045 (28000)
- JAVA设置流中当前位置_java文件流的问题!急
- oracle表和对象基础维护笔记
- python--gevent协程及协程概念
- PHP系列(十三)PHP会话控制
- JAVA常见算法题(四)
- Talib技术因子详解(八)
- 学习《软件评测师教程》
- go 获取本机ip地址
- 恢复扩容U盘实际容量 检查正版U盘 U盘量产工具 U盘修复工具使用方法
- 向日葵设置开机自启动
- 程序员 大牛 面试
- 实验:非骨干区域通过虚链路穿越非骨干区域连接骨干区域实现互联互通
- 计算机二级ppt云计算,2021年全国计算机等级考试二级officeppt演示文稿题目.docx
热门文章
- 获取注册表信息-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography的MachineGuid的值
- Qt5.9/C++架构实例(一个简单的MCV架构应用实例)
- 2023 XL软件库App后端源码 可自定义易支付 完整版
- 【机器学习】补完计划
- unsw计算机科学的挂科率,2020年新南威尔士大学研究生挂科率
- 新南威尔士大学计算机博士申请,2020年新南威尔士大学博士申请时间
- java 数学公式解析框架有哪些_开源工具 | 推荐几个Gitee火热Java项目
- 华为手机不能支持5G,研发创新科技解决,M国的做法落空
- c语言 统计已初始化的二维数组a[3][4]中非零元素的个数(用指针实现)
- 平面解析几何----圆锥曲线焦点弦上焦半径的倒数和为ep分之2的初等几何证明