您的位置:首页 > 其它

动态规划习题总结

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]往往单调递增,有时可以利用这个转化问题。

                   

      

    





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: