DP(Dynamic programming)——尽力学习之中(2016 HUAS ACM 暑假集训-5)
这周不打算按照以往的方式更新博客,而是采用整体的方式。一是因为学的太少,没东西写;二是这篇博客会经常更新的。如题,DP——尽力学习之中。
------------------------------------------------------------------------------------------------------------------------------------------------------------------
先说几个与训练不太相关的东西
一、DP分类:
基础DP、线形DP、概率DP、区间DP、树形DP、数位DP、状态压缩DP......
------------------------------------------------------------------------------------------------------------------------------------------------------------------
二、DP问题满足的性质:
①最优子结构性质:如果问题的最优解所包含的子问题的解也是最优的,则称该问题具有最优子结构性质(也称满足最优化原理)。
②子问题重叠性质:在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划利用这种子问题的重叠性质,对每一个子问题只计算一次(记忆化搜索),然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而效率较高。
③无后效性:将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。
------------------------------------------------------------------------------------------------------------------------------------------------------------------
心得总结:
DP之一:基础DP(背包) 借鉴资料——背包九讲
Case1:0 1背包:有N件物品,每种物体只有一种(第i种物品的价值是value[i],所占空间是volume[i]),决策只有拿与不拿。给定背包总空间V,求在不超过V的情况下的 MAX value。
若用f[i][V]表示前i件物品恰放入一个容量为V的背包可以获得的最大价值,对于物品i,两种策略:
1.如果拿:则value = ( f[i-1][ V-volume[i] ] ) + value[i]; //前i-1件物品value+第i件物品value
2.如果不拿:则value = f[i-1][V].
于是很容易得到状态转移方程:f[i][V] = max( f[i-1][V] , f[i-1][V-volume[i] + value[i] )
采用一维数组的话:用f[0...V]表示,f[V]表示把前i件物品放入容量为V的背包里得到的价值。
表示方法:dp[j] = max ( dp[ j ] , dp[ j - volume[i] ] + value[i] )
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Case2:完全背包:有N件物品,每种物体有无限种(第i种物品的价值是value[i],所占空间是volume[i]),决策是拿多少件。给定背包总空间V,求在不超过V的情况下的 MAX value。
0 1背包和完全背包非常相似,只是一个顺序(对于物品i,完全背包可以拿多次,所以是顺序,0 1背包只能拿一次,所以是逆序)不同,为方便起见,把两者的核心代码写在一起。
顺便提一下,在顺序上,与你采用的数组有关。用二维数组的话,0 1背包也是可以顺序的。但是我们为了节约空间,一般采用一维数组,所以要注意顺序。
for(int i=0; i<n; i++)//n件物品
{
for(int j=m; j>=volume[i]; j--)//逆序->0 1背包 //for(int j=volume[i]; j<=m; j++)//顺序->完全背包
dp[j] = max( dp[j], dp[ j - volume[i] ] + value[i] );//比较第i种与第j种所得价值的大小
}
cout << dp[m] << endl;
训练中遇到的:
第四周训练的M题(0 1 背包)http://acm.hust.edu.cn/vjudge/contest/125308#problem/M
第五周训练的G题(完全背包)http://acm.hust.edu.cn/vjudge/contest/126708#problem/G
------------------------------------------------------------------------------------------------------------------------------------------------------------------
Case3:多重背包:有N件物品,第i种物体有n[i]种(第i种物品的价值是value[i],所占空间是volume[i])。给定背包总空间V,求在不超过V的情况下的 MAX value。
对于多重背包,可在完全背包的基础上进行修改,与之不同的是,对于第i件物品,有n[i]+1种策略(取0~n[i]件)。
于是可以得出状态转移方程(二维数组表示):f[i][V] = max( f[i-1][V] , f[i-1][V - k*volume[i]] + k*value[i])(0<=k<=n[i] )
一维数组表示:dp[j] = max( dp[j] , dp[i-1][V - k*volume[i]] + k*value[i] )
如果数据量比较大,多重背包复杂度比较高,建议优化。下面仅提供几种参考
1.若两件物品i、j满足volume[i]<=volume[j]且value[i]>=value[j],则将物品j去掉,这个优化显然正确。因为任何情况下都可将价值小费用高得j换成物美价廉的i,得到至少不会更差的方案。然而这个并不能改善最坏情况的复杂度,因为有可能特别设计的数据可以一件物品也去不掉。这个优化可以简单的O(N^2)地实现,一般都可以承受。
2.针对背包而言,可以首先将费用大于V的物品去掉,然后使用类似计数排序的做法,计算出费用相同的物品中价值最高的是哪个,可以O(V+N)地完成这个优化。
3.还可以考虑把完全背包转化为0 1背包来解,最简单的想法是:将一种物品拆成多件物品。
4.更高效的转化方法是(二进制优化):把第i种物品拆成费用为volume*2^k、价值为value*2^k的若干件物品,其中k满足0<=k<=log2(V/volume)+1。这是二进制的思想,因为不管最优策略选几件第i种物品,总可以表示成若干个2^k件物品的和。这样把每种物品拆成O(log2(V/volume))件物品,这是一个很不错的优化。
训练中遇到的:第五周的H题:http://acm.hust.edu.cn/vjudge/contest/126708#problem/H
背包暂时写到这里,混合背包看着有点晕,以后更新。
------------------------------------------------------------------------------------------------------------------------------------------------------------------
DP之二:线性DP(不定时更新中......)
Case1:最长递增子序列问题(LIS)
Case2:最长公共子序列问题(LCS)
Case3:子集和问题(subset sum)
DP(Dynamic programming)——尽力学习之中(2016 HUAS ACM 暑假集训-5)的更多相关文章
- [LeetCode] 198. House Robber _Easy tag: Dynamic Programming
You are a professional robber planning to rob houses along a street. Each house has a certain amount ...
- Python算法之动态规划(Dynamic Programming)解析:二维矩阵中的醉汉(魔改版leetcode出界的路径数)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_168 现在很多互联网企业学聪明了,知道应聘者有目的性的刷Leetcode原题,用来应付算法题面试,所以开始对这些题进行" ...
- 强化学习三:Dynamic Programming
1,Introduction 1.1 What is Dynamic Programming? Dynamic:某个问题是由序列化状态组成,状态step-by-step的改变,从而可以step-by- ...
- 动态规划 Dynamic Programming 学习笔记
文章以 CC-BY-SA 方式共享,此说明高于本站内其他说明. 本文尚未完工,但内容足够丰富,故提前发布. 内容包含大量 \(\LaTeX\) 公式,渲染可能需要一些时间,请耐心等待渲染(约 5s). ...
- 动态规划算法(Dynamic Programming,简称 DP)
动态规划算法(Dynamic Programming,简称 DP) 浅谈动态规划 动态规划算法(Dynamic Programming,简称 DP)似乎是一种很高深莫测的算法,你会在一些面试或算法书籍 ...
- 动态规划(Dynamic Programming, DP)---- 最大连续子序列和
动态规划(Dynamic Programming, DP)是一种用来解决一类最优化问题的算法思想,简单来使,动态规划是将一个复杂的问题分解成若干个子问题,或者说若干个阶段,下一个阶段通过上一个阶段的结 ...
- 算法导论学习-Dynamic Programming
转载自:http://blog.csdn.net/speedme/article/details/24231197 1. 什么是动态规划 ------------------------------- ...
- dynamic programming 学习
这是看到一位大神,写的关于dynamic programming的博客,认为很好.简单分析下.然后给出链接. 背景问题就是 有一个国家,全部的国民都很老实憨厚,某天他们在自己的国家发现了十座金矿.而且 ...
- 对动态规划(Dynamic Programming)的理解:从穷举开始(转)
转自:http://janfan.cn/chinese/2015/01/21/dynamic-programming.html 动态规划(Dynamic Programming,以下简称dp)是算法设 ...
随机推荐
- 更新centos curl
centos curl 默认使用nss,而不是openssl 升级curl让curl支持openssl rpm -Uvh http://www.city-fan.org/ftp/contrib/yum ...
- linux test 命令使用
1. 关于某个文件名的『类型』侦测(存在与否),如 test -e filename -e 该『文件名』是否存在?(常用) -f 该『文件名』是否为文件(file)?(常用) -d 该『文件名』是否为 ...
- 清除mysql表中数据
delete from 表名; truncate table 表名; 不带where参数的delete语句可以删除mysql表中所有内容,使用truncate table也可以清空mysql表中所有内 ...
- 【EXCEL】冻结窗口的设置
在excel使用时,表格内容很多时,为查看方便,需要冻结一部分内容,冻结窗口分为以下几种情况,分别进行解析. 工具/原料 excel 冻结首行 1 打开需要的表格,点击“视图”----冻结窗格,点击“ ...
- Objective-C Memory Management
Objective-C Memory Management Using Reference Counting 每一个从NSObject派生的对象都继承了对应的内存管理的行为.这些类的内部存在一个称为r ...
- windows 下用eclipse搭建java、python开发环境
本人只针对小白!本文只针对小白!本文只针对小白! 最近闲来无事,加上之前虽没有做过eclipse上java.python的开发工作,但一直想尝试一下.于是边查找资料边试验,花了一天时间在自己的机器上用 ...
- lightoj1348
//Accepted 6004 KB 924 ms /* source: lightoj1348 time :2015.5.29 by :songt */ /*题解: 树链剖分 */ #include ...
- JS在火狐浏览器下如何关闭标签?
首先,要确定火狐设置是否允许通过JS代码window.close()方法关闭标签. 确定方式如下: 在Firefox地址栏里输入 about:config 在配置列表中找到dom.allow_scri ...
- 基于css3的轮播效果
花了一上午来调整页面在ie10上的显示问题,sass编译生成的css文件在ie内核下一直不能正确加载,果然兼容性的问题还需要好好研究.转入正题,用css3实现轮播效果主要是基于css3的framewo ...
- 关于android的UI更新机制与误区
Android系统的消息队列和消息循环都是主线程的,其它后台服务等无法直接更新,必须通过下面的消息队列,由主线程的消息循环去依次执行更新ui: 同时对于费时间超过5秒的事件,比如网络链接等,建议新开线 ...