动态规划习题总结
2015-11-29 22:24
417 查看
1.背包问题
01背包
uva 562 - Dividing coins :
tot是一定的,如果某个值x能够到达,那么tot-x一定能到达
只用从i=tot/2 逐渐减小 开始检查 是否i和tot-i都能到达
动态规划过程中,只用求出0到tot/2是否能达到即可。
hdu 2955 Robberies :
01背包,被抓住的概率应该是一连串概率的乘积,因为把概率当作背包体积不好计算,而且浮点数本身就有精度问题,
这个题目得把得到的钱数当作背包的体积,生还的概率当作价值。
poj 2184 Cow Exhibition
01背包,对一头牛的两个值a、b,一个看成花费,一个看成是价值。
这也是数组的运用dp[],一个数组其实就是一个映射。在x->dp[x]中,不仅要注意dp[x]的意义,还要充分利用x的意义。
dp[x]表示a值总和为x时,b值和的最大值。
如果花费大于0(一般的01背包),要逆序遍历。
如果花费小于0, 则要升序。
虽然总体积有负数值,我们可以按一定的规则把它存到对应的正值下标x的dp[x]下。
hdu
2639 Bone Collector II
要求出第k大的价值,经典的背包拓展成二维,dp[v][t]表示容量为v的背包能装的第t大的价值。
状态转移类似于一个归并排序。
背包问题的dp其实有两种意义,对应不同的转移。
dp[x]既可以表示容量为x的背包对应的最大价值,(此时初始化均为0)
又可以表示装载了x体积对应的最大价值。(此时dp[0]初始化为0。其余可以为负值了 ,表示达不到。)
poj 2923 Relocation
除了状态压缩,感觉这题是真正的dp基础题(我是说dp的思路简单)。但是道好题,整体是有难度的。
hdu 3466 Proud Merchants
顺序性,排序相关。考虑好顺序则简单。细想还是挺难的。
排序要求:need2-cost2>=need1-cost1(2物品后考虑,1物品先考虑,分阶段动态规划,1物品在前)
关键是按顺序,本次转移利用的状态要是先前计算好了的。
对于排序的考虑,只要考虑任意两个物品之间怎么排即可。
hdu
2126 Buy the souvenirs 01背包+计数dp
01背包+计数DP
价值为0时,方法种数为1
hdu 4281 Judges' response
集合DP+TSP
集合x是s的子集: s==x|s , x==x&s
集合x与s的有交集: x&s
对于集合s,求它的所有非空真子集: for(int x=(s-1)&s ; x ;x=(x-1)&s ) { }
很方便修改为子集。
01背包:每个物品只能用一次,
dp[v][i]=min( dp[v-cost][i-1]+val[i],dp[v][i])
其核心思想实质是: 分阶段动归,考虑了第i种物品的结果= 现在试加入第i物品一个,然后将其与 前i-1个物品的结果
综合考虑。
不论转移方程具体如何,其本质如此。
当前利用的结果一定是之前计算好的。对此要设计好顺序性及排序方法。
dp[v] =min( dp[v-cost]+val[i],dp[v])
完全背包
UVA 674 Coin Change 完全背包虽然网上说这是基础题,感觉其实并不简单,虽然有人将此题归为完全背包,但感觉和经典的背包转移还是有些差别。
dp[x][i]表示体积为x时的,前i种物品,能达到的方法种数。
状态转移方程:
dp[x][i] =dp[x][i-1]+dp[x-cost[i]][i];
意味对于体积为x的背包,若考虑将状态从只用了前i-1种物品,转移到用了前i种物品。
则要将原来的状态 加上 用了第i种物品时种类数。(其实在x-cost[i]时就已经证明用了第i种物品了)
可用一维数组表示。
代码
UVA 147 - Dollars 完全背包
必须对精度作出处理。推荐其中一种精度的处理方法。
可以将5c当作1处理,节约数组空间。因为货比都是5的倍数
对于计数dp,一定要想到long long和取模。
代码
poj 3181 大数/高精度的完全背包
大数的钱币兑换问题
代码
zoj 3623 动态规划的无后效性 + 问题转化
zoj 3524 拓扑排序+背包
zoj 3662 分阶段动归
多重背包
poj 3260 The Fewest Coins混合背包(完全+多重)+上限处理
poj 2063 Investment 贪心+完全背包
贪心:只要每年的选择获利最大即可。
poj 1276 裸多重背包
hdu 1509 多重背包,超水
poj 2392 排序(贪心)+dp(背包)
总结一下,多重背包就是分解成多个0、1背包。完全背包和多重背包考得似乎比01背包多。
dp[v]的意义:有些题目是指体积v的背包能创造最大价值,(不必装满)
有的题目是指完全装满体积v,能得到的最大价值。
像钱币兑换问题,dp[v]时价值一定是v,此时可以用bool型表示dp[v]能否达到。
像钱币兑换的计数dp,dp[v]+=dp[v-cost],dp[v]表示目前凑成v价值的方法数。
使用动态规划,先要看问题的规模,
然后在关键有几个:1.是找到适当的状态能表示起点和终点。
2.是状态转移方程必须满足无后效性。(通常符合了这一点应该就可以写出状态转移方程)
3. 最优子结构,只有满足才能用dp
4. 按合理的顺序进行动态规划
其中第三点是使用dp的基础,难点在于1、2、4三点,如果考察到2,感觉2最难,2和4的联系很紧密。
个人感觉,背包模型很有用,用的时候要找到物品的“花费”和“价值”,才能对应到题目上去。
关于顺序性的设计与枚举有密切联系,枚举的层次变换了,往往代表不同的意义。
一般来说“消耗”较少,“价值”可能会较大,因为存储空间有限啊!
对于 dp[v],举个极端的情形: v就代表数量,我要从100个人中找到10个人,dp[10]代表10个人能到达的某种效果,
这里的dp[v]是指实际到达了v,而不是花费<=v。一个人的cost自然是1,
给出一个for循环 for(int v=0;v<=V;v++)
其实这样就成了分阶段的动归了。
背包的实质是分阶段动归,然而通常01背包和完全背包被省略了一维。
1.对于一般的背包问题,dp[x]往往单调递增,有时可以利用这个转化问题。
相关文章推荐
- POJ 3723 Conscription(kruskal算法求最大权森林问题)
- Maven编译jar出现:无法确定 T 的类型参数的异常的原因和处理方案
- HDU 搬砖
- SpringMVC中的HandlerAdapter
- #include中用双引号和用尖括号括起来头文件的区别
- HTTP Content-type
- hpuoj 1722: 感恩节KK专场——与学妹滑雪 (最短路&精度)
- uva 562 Dividing coins 01背包
- LeetCode -- Find the Duplicate Number
- Ceph 基本数据结构(1)-object
- homerHEVC代码阅读(8)——基础结构之henc_thread_t
- oracle事务隔离机制
- 浅谈c#委托的四种用法及lambda匿名委托
- 理解JavaScript中的闭包
- spring MVC中的异常统一处理
- Linux 线程同步的三种方法
- 第十一周项目1-验证算法(1)层次遍历算法的验证
- static变量与普通变量的区别
- 使用SIGALRM信号为阻塞操作设置超时
- Spark DAGScheduler模块源码解析(转自:http://guozhongxin.com/tag/spark.html)