【输出方案】

一般而言,背包问题是要求一个最优值,如果要求输出这个最优值的方案,可以参照一般动态规划问题输出方案的方法:记录下每个状态的最优值是由状态转移方程的哪一项推出来的,换句话说,记录下它是由哪一个策略推出来的。便可根据这条策略找到上一个状态,从上一个状态接着向前推即可。

还是以01背包为例,方程为f[i][v]=max{f[i-1][v],f[i-1][v-w[i]]+c[i]}。再用一个数组g[i][v],设g[i][v]=0表示推出f[i][v]的值时是采用了方程的前一项(也即f[i][v]=f[i-1][v]),g[i][v]表示采用了方程的后一项。

注意这两项分别表示了两种策略:未选第i个物品及选了第i个物品。

那么输出方案的伪代码:

/*设最终状态为f[N][V]*/
i=N
v=V
while(i>0)if(g[i][v]==0)print "未选第i项物品"else if(g[i][v]==1)print "选了第i项物品"v=v-c[i]

另外,采用方程的前一项或后一项也可以在输出方案的过程中根据f[i][v]的值实时地求出来,即不须纪录g数组,将上述代码中的g[i][v]==0改成f[i][v]==f[i-1][v],g[i][v]==1改成f[i][v]==f[i-1][v-w[i]]+c[i]

【输出字典序最小的最优方案】

这里“字典序最小”的意思是1..N号物品的选择方案排列出来以后字典序最小。

以输出01背包最小字典序的方案为例。

一般而言,求一个字典序最小的最优方案,只需要在转移时注意策略。

首先,子问题的定义要略改一些。我们注意到,如果存在一个选了物品1的最优方案,那么答案一定包含物品1,原问题转化为一个背包容量为v-w[1],物品为2..N的子问题。

反之,如果答案不包含物品1,则转化成背包容量仍为V,物品为2..N的子问题。

不管答案怎样,子问题的物品都是以i..N而非前所述的1..i的形式来定义的,所以状态的定义和转移方程都需要改一下。但也许更简易的方法是先把物品逆序排列一下,以下按物品已被逆序排列来叙述。

在这种情况下,可以按照前面经典的状态转移方程来求值,只是输出方案的时候要注意:从N到1输入时,如果f[i][v]==f[i-v]及f[i][v]==f[i-1][f-c[i]]+w[i]同时成立,应该按照后者(即选择了物品i)来输出方案。

【求方案总数】

对于一个给定了背包容量、物品费用、物品间相互关系(分组、依赖等)的背包问题,除了再给定每个物品的价值后求可得到的最大价值外,还可以得到装满背包或将背包装至某一指定容量的方案总数。

对于这类改变问法的问题,一般只需将状态转移方程中的max改成sum即可。

例如若每件物品均是完全背包中的物品,转移方程为:f[i][v]=sum{f[i-1][v],f[i][v-w[i]]},初始条件:f[0][0]=1。

事实上,这样做可行的原因在于状态转移方程已经考察了所有可能的背包组成方案。

【最优方案的总数】

这里的最优方案是指物品总价值最大的方案。

以01背包为例。

结合求最大总价值和方案总数两个问题的思路,最优方案的总数可以这样求:f[i][v]意义同前述,g[i][v]表示这个子问题的最优方案的总数,则在求f[i][v]的同时求g[i][v]的伪代码如下:

for i=1..Nfor v=0..V{ f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}g[i][v]=0if(f[i][v]==f[i-1][v])inc(g[i][v],g[i-1][v]if(f[i][v]==f[i-1][v-c[i]]+w[i])inc(g[i][v],g[i-1][v-c[i]])}

【求次优解、第K优解】

对于求次优解、第K优解类的问题,如果相应的最优解问题能写出状态转移方程、用动态规划解决,那么求次优解往往可以相同的复杂度解决,第K优解则比求最优解的复杂度上多一个系数K。

其基本思想是将每个状态都表示成有序队列,将状态转移方程中的max/min转化成有序队列的合并。

这里仍然以01背包为例。

首先看01背包求最优解的状态转移方程:f[i][v]=max{f[i-1][v],f[i-1][v-w[i]]+c[i]}。如果要求第K优解,那么状态f[i][v]就应该是一个大小为K的数组f[i][v][1..K]。其中f[i][v][k]表示前i个物品、背包大小为v时,第k优解的值。

“f[i][v]是一个大小为K的数组”可以简单地理解为在原来的方程中加了一维。显然f[i][v][1..K]这K个数是由大到小排列的,所以我们把它认为是一个有序队列。

然后原方程就可以解释为:f[i][v]这个有序队列是由f[i-1][v]和f[i-1][v-w[i]]+c[i]这两个有序队列合并得到的。有序队列f[i-1][v]即f[i-1][v][1..K],f[i-1][v-w[i]]+c[i]则理解为在f[i-1][v-w[i]][1..K]的每个数上加上c[i]后得到的有序队列。

合并这两个有序队列并将结果(的前K项)储存到f[i][v][1..K]中的复杂度是O(K)。最后的答案是f[N][V][K]。总的复杂度是O(NVK)。

实际上,一个正确的状态转移方程的求解过程遍历了所有可用的策略,也就覆盖了问题的所有方案。只不过由于是求最优解,所以其它在任何一个策略上达不到最优的方案都被忽略了。如果把每个状态表示成一个大小为K的数组,并在这个数组中有序的保存该状态可取到的前K个最优值。那么,对于任两个状态的max运算等价于两个由大到小的有序队列的合并。

另外还要注意题目对于“第K优解”的定义,将策略不同但权值相同的两个方案是看作同一个解还是不同的解。如果是前者,则维护有序队列时要保证队列里的数没有重复的。

动态规划 —— 背包问题 P09 —— 背包问题的变化相关推荐

  1. 0-1背包问题 动态规划java_C#使用动态规划解决0-1背包问题实例分析

    // 利用动态规划解决0-1背包问题 using System; using System.Collections.Generic; using System.Linq; using System.T ...

  2. 算法导论——动态规划:0-1背包问题(完全解)

    2019独角兽企业重金招聘Python工程师标准>>> package org.loda.dynamic;import org.junit.Test;/*** * @ClassNam ...

  3. 动态规划算法-03背包问题

    背包问题 简介 背包问题一个很著名的动态规划问题,也称为0-1背包问题,很多题都是以此为模板进行魔改的. 问题描述 有N个重量为w1,w2,w3,,,wn且价值为v1,v2,v3,,,vn的物品和一个 ...

  4. 经典动态规划:0-1 背包问题

    经典动态规划:0-1 背包问题 文章目录 经典动态规划:0-1 背包问题 一.题目描述 二.动规标准套路 三.题目描述 四.解法分析 五.优化 一.题目描述 就讨论最常说的 0-1 背包问题,简单描述 ...

  5. 【动态规划】简单背包问题II

    问题 J: [动态规划]简单背包问题II 时间限制: 1 Sec  内存限制: 64 MB 提交: 127  解决: 76 [提交] [状态] [讨论版] [命题人:admin] 题目描述 张琪曼:& ...

  6. 【动态规划】完全背包问题

    问题 O: [动态规划]完全背包问题 时间限制: 1 Sec  内存限制: 64 MB 提交: 151  解决: 71 [提交] [状态] [讨论版] [命题人:admin] 题目描述 话说张琪曼和李 ...

  7. 动态规划在求解背包问题中的应用(JAVA)--回溯法、记忆化法

    动态规划在求解背包问题中的应用 背包问题向来是动态规划的典型问题,给定n个重量为w1,w2,...,wn,价值为v1,v2,...,vn的物品和一个称重量为W的背包,求这些物品中最优价值的一个子集,且 ...

  8. 动态规划解决0-1背包问题详解(图文并茂)

    动态规划解决0-1背包问题 这个是网上比较好的案例,因为原文有些地方晦涩难懂,对于刚接触动态规划问题的朋友来说很不友好,所以很对地方加入了我自己的见解,也是作为我的一次学习历程. 一.问题描述: 有n ...

  9. 动态规划之 0-1 背包问题

    动态规划问题一直以来都是利用空间换取时间. 动态规划问题一直以来最经典的就是 0 1背包问题 ,再有点难度就是 完全背包问题 以及多重背包问题 0-1背包问题 题目描述:有一个容量为 V 的背包,和一 ...

最新文章

  1. 扎克伯格|在美国国会数据门听证会上的证词-中英文全文
  2. 17、mybatis两个内置参数
  3. 标识人脸程序matlab,Matlab人脸识别基础源程序
  4. Accoridion折叠面板
  5. 使用php创建一个注册表单,如何实现一个简单的注册表单
  6. ajax on ture,细数Ajax请求中的async:false和async:true的差异
  7. 计算机编程语言的分类与python语言快速度认识
  8. C语言笔记(数组地址一些细节)
  9. free mybatis 不生效_这些Mybatis-Plus的使用小技巧,你应该知道的!
  10. automak 和 autoconf 介绍
  11. mysql图书管理系统er图,图书管理系统er图.doc
  12. 如何安装matlab2016b
  13. “创作大师——(PyTorch)RNN”
  14. Android 子线程 UI 操作真的不可以?
  15. python的invalid syntax是什么意思_请问在python 中 出现 invalid syntax 是什么意思 ?
  16. Java中常见的30道例题(附代码)
  17. ios app 应用内购买配置完全指南
  18. 汽车在线升级系统(OTA)开发浅析
  19. 谈一谈什么是接口测试?怎样做接口测试?
  20. 龚胤全云栖大会_2018云栖大会

热门文章

  1. 一条SQL引发的“血案”:与SQL优化相关的4个案例
  2. 一文读懂「中台」的前世今生
  3. 2018年AI专业最全报考指南:去哪学?怎么去?
  4. 终于有人说清楚了!内卷和努力到底有啥区别?
  5. 写了4年博客,我终于也出了一本书。
  6. JeecgBoot版本4月份新版即将发布,抢先体验。。
  7. 【JEECG Dubbo专题】Dubbo+Zookeeper+Spring整合应用篇-Dubbo基于Zookeeper实现分布式服务(二)
  8. 轻量级J2EE持久层解决方案,MiniDao-PE版 1.5.4【版本发布】
  9. Node.js初探之hello world
  10. 一位面试了阿里,滴滴,网易,蚂蚁金服,最终有幸去了网易的Java程序员【面试题分享】...