高效算法之动态规划(第15章)

有人说:越炫耀什么,越缺少什么。但我却以为:越缺少什么,越觉得别人炫耀什么。 ——李宫俊《李宫俊的诗》

0. 前言

参考图书《算法导论》
  动态规划通常用来解决最优化问题,在这类问题中,我们通常做出一组选择来表达最优解。在做出这个选择的同时,通常会生成与原问题形式相同的子问题。当多于一个选择子集都生成相同的子问题时,动态规划技术通常很有效,其关键技术就是对每一个这样的子问题都保存其解,当其重复出现的时候即可避免重复求解。这种思想可以将指数时间的算法转换为多项式时间的算法。
  动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。动态规划(dynamic programming)中的programming指的是一种表格法,不是编写计算机程序。
  

1. 动态规划解析

采用动态规划求解的问题的一般要具有3个性质:

(1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
(2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
(3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)。

动态规划求解基本步骤:

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

2. 动态规划的应用

2.1 钢条切割

问题陈述:给定一个长度为n英寸的钢条和一个价格表pii=1,2,3,4....,n,求切割钢条的方案,使得销售收入最大。

长度i12345678910
价格pi1589101717202430

问题分析:从题目中我们可以得出给定的长度为n的钢条有2n1种不同的切割方案,因为在距离钢条左端i(i=1,2,3..,n1)英寸处,我们总是可以选择切割或者不切割。对于上述的价格表样例,我们可以观察所有最优收益值ri(i=1,2,3,4...10) 以及对应的最优切割方案:

r1=1, 切割方案1=1(无切割)
r2=5, 切割方案2=2(无切割)
r3=8, 切割方案3=3(无切割)
r4=10, 切割方案4=2+2
r5=13, 切割方案5=2+3
r6=17, 切割方案6=6(无切割)
r7=18, 切割方案7=6+1或者7=2+2+3
r8=22, 切割方案8=2+6
r9=25, 切割方案9=3+6
r10=30, 切割方案10=10(无切割)
  更一般的对于rn(n>=1), 我们可以用更短的钢条的最优切割收益来描述它:

rn=max(pn,r1+rn1,r2+rn2,r3+rn3....rn2+r2,rn1+r1)

注意,为了求解规模为n的原问题,我们求解形式完全一样(最优解结构特征刻画),完成首次切割之后我们将两段钢条看作两个独立的钢条切割问题,通过组合两个相关子问题的最优解(最优子结构),并且在所有可能的两段切割方案中选取组合收益最大者,构成原问题的最优解。
除了上述求解方式还有一种递归求解的方式公式如下:
rn=max(pi+rn1)(1in)

算法设计:
自顶向下的普通递归算法设计:

SteelCut(p[],n){//初次判断if(n==0){return 0;}int q=-1;//不做切割if(n<=p.length){q=p[n];}//递归求解for(i=1 to n){q=max(q,p[i]+SteelCut(p[],n-i));}return q;
}

使用动态规划的算法设计:

//算法1:带备忘录的自顶向下法
MemorizedSteelCut(p[],n){int r[] = new int[n];for(i=0 to n){r[i]=-1;}return MemorizedSteelCutAux(p[],n,r);
}
MemorizedSteelCutAux(p[],n,r){if(r[n]>=0){return r[n];}if(n==0){q=0;}else{q=-1;for(i=1 to n){q=max(q,p[i]+MemorizedSteelCutAux(p[],n-i,r));      }}r[n]=q;return q;
}//算法2:自底向上法
BottomUpSteelCut(p[],n){int r[] = new int[n];r[0]=0;for(j=1 to n){q=-1;for(i=1 to j){q=max(q,p[i]+r[j-i]);}r[j]=q;}
}

Java实现:

package lbz.ch15.dp.ins1;
/** * @author LbZhang* @version 创建时间:2016年3月4日 下午2:20:33 * @description 钢条切割问题*/
public class SteelCutting {public static void main(String[] args) {System.out.println("DP 在钢条切割问题中的应用 ");int price[] = {1,5,8,9,10,17,17,20,24,30};int n = 10;//自顶向下的递归实现int result = 0;result = TopToBottomRecursion(price,n);System.out.println("常规的思路:"+result);//使用动态规划来实现  备忘录result=MemorizedSteelCut(price,n);System.out.println("备忘录法:"+result);//使用动态规划的自底向上非递归的实现result=BottomToTopSteelCut(price,n);System.out.println("自底向上非递归方法:"+result);}private static int BottomToTopSteelCut(int[] price, int n) {int r[] = new int[n+1];r[0]=0;//动态表的开头for(int j=1;j<=n;j++){int q=-1;for(int i=1;i<=j;i++){q=maxOfTwo(q,price[i-1]+r[j-i]);}r[j]=q;}return r[n];}/*** 备忘录方法* @param price* @param n* @return*/private static int MemorizedSteelCut(int[] price, int n) {int r[] = new int[n+1];for(int i=0;i<=n;i++){r[i]=-1;}return MemorizedSteelCutAux(price,n,r);}/*** 辅助过程的备忘录核心算法* @param price* @param n* @param r* @return*/private static int MemorizedSteelCutAux(int[] price, int n, int[] r) {if(r[n]>=0){return r[n];}int q=0;if(n==0){q=0;}else{q=-1;for(int i=1;i<=n;i++){//price[i-1] 应为price的下标是从0开始,q=maxOfTwo(q,price[i-1]+MemorizedSteelCutAux(price,n-i,r));     }}r[n]=q;return q;}/*** //自顶向下的递归实现 常规思路* @param price                                 ``````````````````````````````````````````````````````````````````* @param n* @return*/private static int TopToBottomRecursion(int[] price, int n) {if(n==0) return 0;int q = -1;if(n<=price.length){q=price[n-1];}for(int i=1;i<n;i++){q=maxOfTwo(q,price[i-1]+TopToBottomRecursion(price,n-i));}return q;}private static int maxOfTwo(int x, int y) {return x>y?x:y;//三目运算符的使用}}

重构解-对源程序进行修改

private static int BottomToTopSteelCut(int[] price, int n) {int r[] = new int[n+1];int s[] = new int[n+1];r[0]=0;//动态表的开头for(int j=1;j<=n;j++){int q=-1;for(int i=1;i<=j;i++){//q=maxOfTwo(q,price[i-1]+r[j-i]);if(q<price[i-1]+r[j-i]){q=price[i-1]+r[j-i];s[j]=i;}}r[j]=q;}System.out.println();for(int temp=0;temp<=n;temp++){System.out.print(s[temp]+"|-"+temp+"-|");}System.out.println();//正确的组合输出printToFormal(s);return r[n];}private static void printToFormal(int[] s) {int len=s.length-1;int temp=s[len];System.out.print("钢条切割的组合方式: "+temp+" ");while(temp!=len){len=len-temp;temp=s[len];System.out.print("+ "+temp+" ");}System.out.println();}

2.2 斐波那契数列

下面直接给出斐波那契数列的Java实现的O(n)的动态规划算法实现。

package lbz.ch15.dp.ins1;/*** @author LbZhang* @version 创建时间:2016年3月7日 下午9:42:15* @description 类说明*/
public class MemoryAndTable {static int MAX = 20;static int[] lookUp = new int[MAX];public static int fibMemory(int n) {if (lookUp[n] == 0) {if (n <= 1) {lookUp[n] = n;} else {lookUp[n] = fibMemory(n - 1) + fibMemory(n - 2);}}return lookUp[n];}// //打表(自下而上)public static int fibTable(int n) {int[] f = new int[n + 1];int i;f[0] = 0;f[1] = 1;for (i = 2; i <= n; i++) {f[i] = f[i - 1] + f[i - 2];}return f[n];}public static void main(String[] args) {int n = 5;System.out.println(fibMemory(9));System.out.println();// int res=0;// res=fibTable(9);System.out.println(fibTable(9));}
}

注意:在动态规划中,子问题解决方案被存储在一个表中,以便这些不必重新计算。 因此,如果这个问题是没有共同的(重叠)子问题, 动态规划是没有用的。例如,二分查找不具有共同的子问题。

转载于:https://www.cnblogs.com/mrzhang123/p/5365807.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573917.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

地磅称重软件源码_【漯河衡器】导致地磅称重不准原因及处理措施

地磅是一种新型的大型电子衡器&#xff0c;能够迅速、直观、高准确度地展现工商业、仓储、货站贸易计量的重要工具。做为贸易结算的工具&#xff0c;地磅的可靠性、准确性、科学性有着极为重要的影响。而在货物来往中&#xff0c;地磅是等价交换的桥梁&#xff0c;一旦地磅显现…

寻宝机器人电路板焊接_专业维修淮安市KUKA库卡KRC2机器人回收{机器人调试}

FANUC机器人伺服-023故障排除&#xff1a;FANUCR-2000六轴焊接机器人点焊进程中&#xff0c;J4机械臂显现自动滑动故障&#xff0c;机器人发出伺服故障报警&#xff0c;报警故障码为伺服-023&#xff0c;依据FANUC机器人维修手册&#xff0c;故障代码解释以下&#xff1a;伺服误…

android uber启动动画,仿 Uber 视频背景登录界面以及登录动画

现在有越来越多的 app 的登录/注册界面的背景是播放视频或者 gif&#xff0c;我主要看了 Uber 和 keep 的登录界面再配合拉勾的登录界面仿作了一个登录界面。1.首先&#xff0c;查资料我在 github 上找到了这两个库&#xff1a;-STLBGVideo 这个库是 oc 写的&#xff0c;但你的…

UIMenuController在label中的使用

要想在label中使用 必须是继承于label的分类 //// MYlabel.m// MenuController//// Created by 张明 on 16/3/8.// Copyright © 2016年 张明. All rights reserved.//#import "MYlabel.h"implementation MYlabel- (void)awakeFromNib{ [self setup];…

遍历列表python_Python 遍历List的三种方法

转载至https://www.cnblogs.com/pizitai/p/6398276.html #!/usr/bin/env python # -*- coding: utf-8 -*- if __name__ __main__: list [html, js, css, python] # 方法1 print 遍历列表方法1&#xff1a; for i in list: print ("序号&#xff1a;%s 值&#xff1a;%s&…

名图1.8智能隐藏功能_自动打包不脏手才是真智能,双11销冠,拓牛自动打包垃圾桶体验...

不是吧&#xff01;不是吧&#xff01;都是2020年了&#xff0c;不会还有人不知道电动垃圾桶的存在吧&#xff1f;如果你还不知道&#xff0c;那就跟5G智玩好物一起来看看最新上线的拓牛T Air Lite吧。首先&#xff0c;让我们看一下拓牛T Air Lite的外观。在大众的印象里&#…

android struts2 图片上传,xhEditor struts2实现图片上传

如果想要出现上传按钮,在xhEditor设置以下参数&#xff1a;html5Upload : false //此属性必须为falseupImgUrl : "ImgUpload.action" //上传服务器接口onUpload : insertUpload //服务器返回信息,JSON格式一、前台代码$(function() {…

软件版本号规范

1. 软件版本阶段说明 o Base版: 此版本表示该软件仅仅是一个假页面链接&#xff0c;通常包括所有的功能和页面布局&#xff0c;但是页面中的功能都没有做完整的实现&#xff0c;只是做为整体网站的一个基础架构。 o Alpha版: 此版本表示该软件在此阶段主要是以实现软件功能…

python如何画出多个独立的图片_python实现在一个画布上画多个子图

matplotlib 是可以组合许多的小图, 放在一张大图里面显示的. 使用到的方法叫作 subplot. 均匀画图 使用import导入matplotlib.pyplot模块, 并简写成plt. 使用plt.figure创建一个图像窗口. 1 2 3 import matplotlib.pyplot as plt plt.figure() 使用plt.subplot来创建小图. plt.…

e5cc温控仪通讯参数设定_产品介绍||DeltaWiFi通讯型多功能电表DPMC520W

Delta-WiFi通讯型多功能电表DPM-C520W台达WiFi通讯型多功能电表DPM-C520W &#xff0c;使用无线通信技术&#xff0c;非常适合于挑高空间和不易配线的盘体使用。可支持各种电力参数量测及谐波量测&#xff0c;支持报警设定、参数群组化设定&#xff0c;采用MODBUS-TCP协议&…

酷派删除android系统软件,【玩机教程】酷派手机root后不可删除系统自带程序+组件中英对照...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼〖对照表〗[File|文件] [English] [中文]ApplicationsProvider.apk Search Applications Provider 搜索应用提供程序(不可删除)AppStoreWidget.apk Application recommend 应用推荐(可删除)BackupRestoreConfirmation.apk (不可删除…

python字典程序题_急!一道关于python字典的编程题!求思路!

作业要求做一个python程序导入一个文本文件&#xff08;importsys,file_inopen(sys.argv[1],r))那个文本文件里都是AnimalId&#xff1a;Timestamp&#xff1a;StationId格式的数据比如a45:27-10-2009:s1。下面图片... 作业要求做一个python程序 导入一个文本文件&#xff08;i…

Servlet单实例多线程模式

http://kakajw.iteye.com/blog/920839 前言&#xff1a;Servlet/JSP技术和ASP、PHP等相比&#xff0c;由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的&#xff0c;所以&#xff0c;在编写代码时需要非常细致地考虑多线程的安全性问题。 JSP的…

文件设置索引_什么样的网站结构备受搜索引擎喜爱?

网站在优化中&#xff0c;对于收录问题也非常重视&#xff0c;但很多时候&#xff0c;网站各方面都做的很好但就是蜘蛛不抓取&#xff0c;这个时候就要考虑是网站结构问题了&#xff0c;导致网站页面无法被正常抓取。那么怎样才能提升搜索引擎的抓取呢&#xff1f;什么样的结构…

函数运行 形参实参变化 内存空间_可能python创始人都不知道的,python函数实参形参讲解...

今天我们来学习一下python函数的用法函数是带名字的代码块&#xff0c;我们可以直接调用函数&#xff0c;无需反复板鞋完成该函数的代码1.下面我们来看一个简单的函数首先定义一个函数&#xff0c;def是定义的意思&#xff0c;后面是函数名在函数中同样使用缩进来区分语句是否在…

小说阅读网站设计HTML,40多个漂亮的网页表单设计实例

网页表单是访问者与网站拥有者主要的沟通途径。返馈总是重要的&#xff0c;这就是我们为什么确保网页表单容易理解和使用起来比较直观的原因&#xff0c;尽管如此&#xff0c;甚至在形式设计中它也担当创意中的有效部分。网页表单并非都是乏味的&#xff0c;使用css或flash,你能…

abap 添加alv上的工具栏的按钮_你需要属于自己的PPT工具栏!

人类使用工具的历史&#xff0c;是我们成为人类 &#xff0c;并且不断进步的历史。对于我们设计师而言&#xff0c;认识并掌握设计工具&#xff0c;是我们成为设计师的开始。而根据自己的需要&#xff0c;升级、改造设计工具&#xff0c;则是我们向更深层水平的进阶过程。Power…

window覆盖导航栏

UIView *shangOk [[UIView alloc]initWithFrame:CGRectMake(0, 0, Width, Height-100)]; UIWindow* currentWindow [UIApplication sharedApplication].keyWindow;[currentWindow addSubview:shangOk];转载于:https://www.cnblogs.com/yedayi/p/5262819.html

emlog过滤html,Emlog 搜索优化 标题 + 全文搜索

最近发现&#xff0c;使用搜索功能时&#xff0c;只能搜索到标题含有关键词的文章&#xff0c;或者使用标签搜索到有相同标签的文章。这显然不是我想要的&#xff0c;我希望搜索的结果是&#xff1a;标题中有关键字的文章排在前面&#xff0c;而文章中出现关键字排在后面。所以…

python 小说爬虫_Python实现的爬取小说爬虫功能示例

本文实例讲述了Python实现的爬取小说爬虫功能。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 想把顶点小说网上的一篇持续更新的小说下下来&#xff0c;就写了一个简单的爬虫&#xff0c;可以爬取爬取各个章节的内容&#xff0c;保存到txt文档中&#xff0c;支持持续…