多阶段决策问题,简单地说,每做一次决策就可以得到解的一部分,当所有决策做完之后,完整的解就“浮出水面”了。在回溯法中,每次决策对应于给一个结点产生新的子树,而解的生成过程对应一棵解答树,结点的层数就是“下一个待填充位置”cur。

一、 多段图的最短路

  多段图是一种特殊的DAG,其结点可以划分成若干个阶段,每个阶段只由上一个阶段所决定。

二、0-1背包问题

  0-1背包问题是最广为人知的动态规划问题之一,拥有很多变形。在介绍0-1背包问题之前,先来看一个引例。

【物品无限的背包问题】

  有n种物品,每种均有无穷多个。第 i 种物品的体积为Vi,重量为Wi。选一些物品装到一个容量为C的背包中,使得背包内物品在总体积不超过C的前提下重量尽量大。1<=n<=100,1<=Vi<=C<=10000,1<=Wi<=106。

  分析:它很想上一篇中的硬币问题,只不过“面值之和恰好为S”改成了“体积之和不超过C”,另外增加了一个新的属性——重量,相当于把原来的无权图改成了带权图。这样,问题就变为了求以C为起点(终点任意)的、边权之和最大的路径。

  与前面相比,DAG从“无权”变成了“带权”,但这并没有带来任何困难,此时只需将某处代码从“+1”变成“+W[i]”即可。

  提示:动态规划的适用性很广。不少可以用动态规划解决的题目,在条件稍微变化后只需对状态转移方程做少量修改即可解决新问题。

【0-1背包问题】

  有n种物品,每种只有一个。第i种物品的体积为Vi,重量为Wi。选一些物品装到一个容量为C的背包,使得背包内物品在总体积不超过C的前提下重量尽量大。1<=n<=100,1<=Vi<=C<=10000,1<=Wi<=106。

  分析:刚才的方法已经不适用了:只凭“剩余体积”这个状态,无法得知每个物品是否已经用过。换句话说,原来的状态转移太乱了,任何时候都允许使用任何一种物品,难以控制。为了消除这种混乱,需要让状态转移(也就是决策)有序化。

  引入“阶段”之后,算法便很容易设计了:用d(i , j)表示当前在第i层,背包剩余容量为j时接下来的最大重量和,则d(i , j)= max{d(i+1, j), d(i+1, j-V[i])+W[i]},边界是i >n时d(i , j)= 0,j < 0时为负无穷(一般不会初始化这个边界,而是只当j>=V[i]时才计算第二项)。

  通俗一点讲,d(i , j)表示“把第i,i+1,i+2,…,n个物品装到容量为j的背包中的最大总重量”。事实上,这个说法更加常用——”阶段“只是辅助思考的,在动态规划的状态描述中最好避免”结点“、”层“这样的术语。很多教材和资料直接给出了这样的状态描述,而本书中则是花费了大量的篇幅叙述为什么会想到要划分阶段以及和回溯法的内在联系——如果对此理解不够深入,很容易出现”每次碰到新题自己都想不出来,但一看题解就懂“的尴尬情况。

  提示:学习动态规划的题解,除了要理解状态表示及其转移方程外,最好思考一下为什么会想到这样的状态表示。

  和往常一样,在得到状态转移方程之后,还需思考如何编写程序。尽管在很多情况下,记忆化搜索程序更直观、易懂,但在0-1背包问题中,递推法更加理想。因为当有了“阶段”定义后,计算顺序变得非常明显。

  提示:在多阶段决策问题中,阶段定义了天然的计算顺序。

  下面是代码,答案是d[1][C]:

for(int i=n;i>=1;i--){
for(int j=0;j<=C;j++){
d[i][j] = (i==n ? 0 : d[i+1][j]);
if(j >= V[i]) d[i][j] = max(d[i][j],d[i+1][j-V[i]]+W[i]);
}
}

  正如前面所说,i 必须逆序枚举,但 j 的循环次序是无关紧要的。

DP入门(3)——多阶段决策问题的更多相关文章

  1. 【专章】dp入门

    动态规划(简称dp),可以说是各种程序设计中遇到的第一个坎吧,这篇博文是我对dp的一点点理解,希望可以帮助更多人dp入门. ***实践是检验真理的唯一标准,看再多文章不如自己动手做几道!!!*** 先 ...

  2. 【学习笔记】dp入门

    知识点 动态规划(简称dp),可以说是各种程序设计中遇到的第一个坎吧,这篇博文是我对dp的一点点理解,希望可以帮助更多人dp入门.   先看看这段话 动态规划(dynamic programming) ...

  3. poj 3254 状压dp入门题

    1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...

  4. xbz分组题B 吉利数字 数位dp入门

    B吉利数字时限:1s [题目描述]算卦大湿biboyouyun最近得出一个神奇的结论,如果一个数字,它的各个数位相加能够被10整除,则称它为吉利数.现在叫你计算某个区间内有多少个吉利数字. [输入]第 ...

  5. 【dp入门题】【跟着14练dp吧...囧】

    A HDU_2048 数塔 dp入门题——数塔问题:求路径的最大和: 状态方程: dp[i][j] = max(dp[i+1][j], dp[i+1][j+1])+a[i][j];dp[n][j] = ...

  6. 数位dp入门 hdu2089 不要62

    数位dp入门 hdu2089 不要62 题意: 给定一个区间[n,m] (0< n ≤ m<1000000),找出不含4和'62'的数的个数 (ps:开始以为直接暴力可以..貌似可以,但是 ...

  7. POJ 2342 树形DP入门题

    有一个大学的庆典晚会,想邀请一些在大学任职的人来參加,每一个人有自己的搞笑值,可是如今遇到一个问题就是假设两个人之间有直接的上下级关系,那么他们中仅仅能有一个来參加,求请来一部分人之后,搞笑值的最大是 ...

  8. hdu3555 Bomb 数位DP入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 简单的数位DP入门题目 思路和hdu2089基本一样 直接贴代码了,代码里有详细的注释 代码: ...

  9. HDU 2084 数塔(简单DP入门)

    数塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...

  10. 树形dp 入门

    今天学了树形dp,发现树形dp就是入门难一些,于是好心的我便立志要发一篇树形dp入门的博客了. 树形dp的概念什么的,相信大家都已经明白,这里就不再多说.直接上例题. 一.常规树形DP P1352 没 ...

随机推荐

  1. Python基础—09-文件操作

    文件操作 目录管理(os) system:执行系统命令 # 清空屏幕 # os.system('cls') # 弹出计算器程序 os.system('calc') name:查看系统名称 nt:win ...

  2. js bind的实现

    call,apply,bind都是用来挟持对象或者说更改this指向的,但是区别还是有的,call 传参是 fn.call(this,1,2,3) apply传参是 fn.apply(this,[1, ...

  3. 【Nowcoder 上海五校赛】二数(模拟)

    题目描述: 我们把十进制下每一位都是偶数的数字叫做“二数”. 小埃表示自己很聪明,最近他不仅能够从小数到大:2,3,4,5....,也学会了从大数到小:100,99,98...,他想知道从一个数开始数 ...

  4. dom4j里面封装方法的操作

    animal.xml <?xml version="1.0" encoding="UTF-8"?><animal>   <cat ...

  5. djangorestframework怎么这么好用!

    一年前就已经用过restframework, 当时觉得这个只是给web框架打辅助的, 他能实现的我也都实现(可能没有那么好用, 嘿嘿) 但是我有一种东西叫做效率, 时间就是金钱, 别人造好的就直接用就 ...

  6. php常见面试(Smarty及相关知识)

    1.Smarty简介: 是一种php模板引擎,它分开了后台程序和前台页面内容,使程序员和美工分工合作.还有其它模版引擎实现同样的目的. 2.Smarty使用: 建立php文件: 包含smarty类文件 ...

  7. MAC和windows开发操作系统环境,解决Maven工程中报 Missing artifact jdk.tools:jdk.tools

    同事使用的是苹果mac,而我们其他人的开发环境是windows jdk1.8 导致同事从git上pull下来的工程,pom文件是直接报错的, windows下的pom文件设置是这样的: <dep ...

  8. 初学tiny4412

    1.解压友善之臂提供的uboot make tiny4412_config make 然后将sd卡插到电脑上,编辑虚拟机,选择对应的usb口(usb3.0兼容),如果没有usb3.0,可能是虚拟机版本 ...

  9. python函数的返回值

    返回值:return1.没有返回值    #不写return    #只写return:结束一个函数    #return None2.有一个返回值    #可以返回任何数据类型    #只要返回就可 ...

  10. HyperLedger Fabric 1.4 区块链开发平台(4.1)

    目前区块链开发平台分“公有链平台”和“联盟链系统”两类,“公有链平台”主要以以太坊为主的平台,可以在该类平台上进行代币的发行和根据各种模块搭建应用:“联盟链系统”主要以超级账本为主的开源系统,该类开源 ...