动态规划总结(01背包 完全背包 多重背包)

一、学习资料

1.UVA DP 入门专题
2.夜深人静写算法(二) - 动态规划
3.算法之动态规划
4.什么是动态规划?动态规划的意义是什么?
5.01背包问题和完全背包问题
6.背包九讲

二、练习题目

1.01背包练习
2.完全背包 多重背包练习
3.UVA的部分题目

三、模型总结

(1)01背包问题

1.模型大意

有n件商品,每件商品仅有一件,并且每件商品有自己的价值v和重量w。现在有一个最大承载重量为m的背包,求解最多能装下价值为多少的商品。

2.状态转移方程

dp[j] = max(dp[j],dp[j-w[i]]+v[i])

3.核心代码片

    for(int i =1; i<=n;++i){for(int j = m; j>=w[i];--j)dp[j] = max(dp[j],dp[j-w[i]]+v[i]);}

4.习题小结

1).HDOJ.2955
结合了概率和独立事件的知识。对于每个银行,小偷有抢或者不抢两种选择,并且每个银行抢不抢,事件发生时独立的。两个独立事件共同发生的概率,为两个事件发生概率的乘积。这是需要注意的。 另外一点就是,在遇到一些概率的问题的时候,通常需要将其转换成其对立事件发生的概率。这样解决起来较为容易。

2).HDOJ.3466
题面本身就是一个简单的01背包问题但是关键在于本题却需要排序,原因是会影响到后续物品的选择。简单来说,破坏了动态规划的无后效性
对于每个商品,尤其能够买的临界值qi和其本身的价格pi,即当手中的钱不够qi的时候,商人就不考虑把第i件商品卖给你了。 比如有以下商品:

label item1 item 2
q q1 q2
p p1 p2

其中 q1 – p1 < q2 – p2
若想把这两件商品全部购买,则至少需要p1+p2的金钱。那么如果我们没有这么多金钱怎么办。这就要考虑到dp时候的状态转移了。
在状态转移的时候,item1能从item2转移的状态区间是[min(q1+p2,m),m],同理,item2能从item1转移的状态区间是[min(q2+p1,m),m]。对于p1+q2或p2+q1,个人的理解是,先买了物品1花费p1,因为现在要对物品2进行状态转移,则需要钱的数量大于q2才可以,否则无法进行状态转移,即物品1的状态没有得到利用,因为我们要尽可能重复的利用这个区间。(p2+q1同理可得)
故对于以上2件商品,我们要看p1+q2和p2+q1孰大孰小。再根据题目数据不难看出 p1 + q2 < p2 + q1。
根据以上的叙述不难得出结论:要按qi-pi的差值升序排序,然再做01背包。那么疑问也油然而生:为什么平常的做01背包也没见排序呀? 这是因为普通的01背包pi==qi,也就是说只要有足够的金钱,就能购买物品。故不需要排序。所以以后做这种类型的dp要留个心眼。

3).HDOJ.2546
这题跟上面的那个题目也有相似之处,由于此题恒定q为5,我们可以采用别的方法来处理。先按照价格降序/升序排序,然后把价格最大的那个留下来(留给那个剩余的5块钱,一边让剩余金额最小)。然后以总金额-5为背包容量,除去最贵的剩余菜为商品做01背包即可。

4).HDOJ.2639
此题本身依旧是一个01背包,但是题目要求输出的是第k最优解,平常题目都是直接输出最优解即可。
根据背包九讲,不难想到肯定要增加一维,使得dp变为二维数组,其中第二维用来表示第K最优解。其次分别2个辅助数组a[],b[],容量以题目中的K为上限。实现方法如下:
a.在做01背包的时候,多增加一层循环,由1->k的循环,用来储存第K个解。将原本的01背包状态转移方程中较大的放到a[]中,较小的放到b[]中。
b.其次对a[],b[]做处理,依次从这2个数组中取出较大的那个,放到dp[i][k].表示第k解。
代码如下:

    for(int i = 1;i<=n;++i){for(int j =m;j>=w[i];--j){int l;for( l = 1;l<=k;l++){a[l] = dp[j-w[i]][l]+v[i];b[l] = dp[j][l];}a[l] = b[l] = -1;int x,y,z; x = y= z = 1;while(z<=k && (a[x]!=-1 || b[y]!=-1)){if(a[x] > b[y]){ dp[j][z] = a[x];x++;}else {dp[j][z] = b[y];y++;}if(dp[j][z] != dp[j][z-1]) z++;}}}

5.总结

1). 不要忘记初始化dp数组,和其他的辅助数组。
2). 在求一些最大最小值,或者是否可以构成的时候,经常讲dp整个初始化为INF,或者将dp[0]初始化为0或者1,这个要具体情况具体分析。

(2)完全背包问题

1.模型大意

有n件商品,每件商品有无数件,并且每件商品有自己的价值v和重量w。现在有一个最大承载重量为m的背包,求解最多能装下价值为多少的商品。

2.状态转移方程

dp[j] = max(dp[j],dp[j-w[i]]+v[i])

3.核心代码片

    for(int i =1; i<=n;++i){for(int j = w[i]; j<=m;++j)dp[j] = max(dp[j],dp[j-w[i]]+v[i]);}

4.习题小结

1).UVA.674
经典的硬币组成问题,问某个金额的组成方案有多少种,注意当数据特别大的时候要开long long数组。
2).HDOJ.2159
这题是带个数限制的完全背包,那么最先想到的就是增加一维来表示个数。

    for(int i =1; i<=k; ++i) {for(int j = a[i].ence; j<=m; ++j)for(int l = 1; l<=s;++l)dp[j][l] = max(dp[j][l],dp[j-a[i].ence][l-1] +a[i].exp);}

5.总结

总的感觉完全背包没有什么难点,基本上就是套状态转移方程即可。

(3)多重背包问题

1.模型大意

有n件商品,第ai件商品有ci件,并且每件商品有自己的价值v和重量w。现在有一个最大承载重量为m的背包,求解最多能装下价值为多少的商品。

2.状态转移方程

**F[i,v] = max{F[i − 1, v − k ∗ Ci
] + k ∗ Wi
| 0 ≤ k ≤ Mi}**

3.核心代码片

一般集合二进制优化和单调队列优化,转换为01背包问题

4.习题小结

二进制优化
即用二进制来表示有限的状态。通俗点讲,就是用1,2,4,8,16……这样的数来表示任意一个有限数字。如3 = 2+1, 7=4+2+1 如果我们把物品的个数,拆分成1个2个4个……在一起的物品,那么就是相当于对这样的物品做出选择,即做01背包。 这样就由多重背包,转换成了01背包的问题。
二进制优化代码:

    for(int i = 0 ;i<6;++i){for(int j =1; j<=c[i]; j<<=1){val[cnt] = j*(i+1);num[cnt++] = j;c[i]-=j;}if(c[i]>0){val[cnt] = c[i] * (i+1);num[cnt++] = c[i];}}

5.总结

一般大部分题目都是使用二进制优化转换成01背包问题,或者是使用单调队列优化,极大提高程序效率。

(4)LCS问题 – 最长公共子序列

1.模型大意

给出2个字符串,求出这两个字符串的最长公共子序列的长度。

2.状态转移方程

if(c1[i] == c2[j]) dp[i][j] =dp[i-1][j-1]+1;
else dp[i][j] = max(dp[i-1][j],dp[i][j-1]);

3.核心代码片

    for(int i =1; i<=len1;++i){for(int j = 1; j<=len2;++j){if(c1[i] == c2[j]) dp[i][j] =dp[i-1][j-1]+1;else dp[i][j] = max(dp[i-1][j],dp[i][j-1]);}}

(5)LIS问题 – 最长上升子序列

1.模型大意

给出一个序列,求出他的最长上升子序列的长度。

2.状态转移方程 + 核心代码片

   for(int i = 2; i<=n;++i){if(a[i]>dp[len]) dp[++len] = a[i];else{int pos = BS(dp,a,1,len,i);dp[pos] = a[i];}}int BS(int dt[],int t[],int left, int right,int i)
{int mid;while(left<right){mid = (left+right)/2;if(dt[mid]>=t[i]) right = mid;else left = mid+1;}return left;
}

动态规划总结(01背包 完全背包 多重背包)相关推荐

  1. 代码随想录算法训练营第46天 | 动态规划 part08 ● 139.单词拆分 ● 关于多重背包 ● 背包问题总结篇

    #139 单词拆分 没做出来.我原来是把string放到dp里,不对,这种做法永远都不对.他问的是什么(能不能构成,true,false)就要放到dp里 (大部分题是这样)下面是不对的思路: 正确co ...

  2. 为了OFFER,菜鸟的我必须搞懂动态规划系列三个背包问题之多重背包(二进制优化方法)

    @Author:Runsen @Date:2020/9/17 多重背包有三层循环,如果数据非常的大,那么程序就会变得非常悲伤.在多重背包的问题,其实更多的是考查多重背包的二进制优化方法.学习二进制优化 ...

  3. 背包问题-【01背包】【完全背包】【多重背包】【多限定条件背包】

    背包问题 给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高. 可参考https://www.cnblogs.com/-guz/p/9866118.h ...

  4. 代码随想录算法训练营第五十天|动态规划:139.单词拆分、多重背包理论基础、背包问题总结

    [139.单词拆分] 这个题目是一个背包问题.但是他稍微有点不太一样.在于这题判断能否装满背包是在判断单词是否出现在字典中,如果出现,就代表能装满. 背包是长度为i的字符串 物品是长度为i-j的子串 ...

  5. 小明打联盟 牛客(背包dp,多重背包)

    链接:https://ac.nowcoder.com/acm/problem/14553 来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放 ...

  6. 01背包模板、全然背包 and 多重背包(模板)

    转载请注明出处:http://blog.csdn.net/u012860063 贴一个自觉得解说不错的链接:http://www.cppblog.com/tanky-woo/archive/2010/ ...

  7. 【qduoj - 142】 多重背包(0-1背包的另类处理,dp)

    题干: ycb的ACM进阶之路 Description ycb是个天资聪颖的孩子,他的梦想是成为世界上最伟大的ACMer.为此,他想拜附近最有威望的dalao为师.dalao为了判断他的资质,给他出了 ...

  8. 01背包模板、完全背包 and 多重背包

    转载请注明出处:http://blog.csdn.net/u012860063 讲解链接:http://www.cppblog.com/tanky-woo/archive/2010/07/31/121 ...

  9. 【python】一篇讲透背包问题(01背包 完全背包 多重背包 二维费用背包)

    面对背包问题,有一个很重要的方程式:状态转移方程式 所以每一种背包问题我都会给出状态转移方程式 #01背包 什么是01背包型问题? 先给大家感受一下01背包型问题: 给定n种物品和一背包.物品i的重量 ...

  10. c++ 多重背包状态转移方程_【模板】各种背包问题amp;讲解

    [模板]各种背包问题&讲解  背包问题集合 一般来说,动态规划(DP)都是初学者最难闯过的一关,而在这里详细解说动态规划的一种经典题型:背包问题. 这里介绍的背包分为以下几种:01背包,完全背 ...

最新文章

  1. linux tar 提示 time stamp xxx in the future 解决方法
  2. python画轨迹曲线-matplotlib绘制随机行走轨迹图
  3. Java 目录操作一(递归创建目录、删除目录、判断目录是否为空、判断文件是否隐藏、获取目录大小、在指定目录中查找文件)
  4. 将Centos的yum源更换为阿里云源
  5. LINQ SQL分组取最近一条记录
  6. 【机器学习案例】酒店用机器学习,预测哪些客人会放鸽子
  7. ubuntu14.04安装V-REP和用户使用手册
  8. Floyd算法 C++实现
  9. 拓端tecdat|Python高维统计建模变量选择:SCAD平滑剪切绝对偏差惩罚、Lasso惩罚函数比较
  10. 网工学习笔记——reboot
  11. 获取图片url的后缀
  12. 15款国内外知名优秀PHP集成环境推荐、PHP绿色集成环境推荐
  13. Java开发社招面试经验:2021最新Java面试笔试
  14. 凤姐的原创诗歌 思想的悲哀
  15. 争议带货达人董明珠:直播带货476亿 却被质疑经销商刷单
  16. selenium+python自动化(完整脚本一)
  17. 图片站选择什么样的服务器好?
  18. 模拟豆机、高尔顿瓶【java】
  19. 1. Java POI 读取、写入Excel(包括样式)的工具类Utils
  20. 阿里天池——利用pandas分析美国总统竞选选票情况

热门文章

  1. Java随笔——Java中被除数为0的四种情况及另一特殊情况
  2. 手把手教你做一个自己的chrome扩展程序
  3. 计算机专业押韵口号16字,最牛班级口号霸气押韵16字
  4. CSS基础介绍(三)
  5. javascript 获得上个月、获取下个月日期
  6. Servlet Jsp(个人笔记)
  7. 故障诊断1—基础理论
  8. 2008年北京奥运会赛程表—— 08-18
  9. VTK、ITK安装及ITK读取图片、VTK显示示例(CMake)
  10. break如何跳出多层循环?