近期DP总结

来源:互联网 发布:java 调用rest接口 编辑:程序博客网 时间:2024/06/06 19:40

归纳几个蛮不错的DP思路:

hotel

keywords: 4 7 宾馆

思考

对于这道来说dp[i][j]表示i个人在j个房间的状态是很容易定义出来的,但是我们发现我们没办法转移………………
为什么呢?对于一个房间的人来说他们的去向不唯一!并且对于一个房间来说就连最后的状态也不唯一,更何况最后房间中人的来源了……
所以这种对房间、对人的定义方法完全就是浪费时间(于是我就浪费了2个小时(哭)
转换思路,更改对象到房间与房间之间的通道上。注意到房间是线性的,所以对于一个通道来说,它所能接受的就只有两种状态:
1.从左边来了<=7个人。
2.从右边来了<=7个人。
思考为什么:因为当移动人数超过7人时,一定不是最优解法,应为既然超过了7个人就应该在之前的房间直接停下了,而不是继续向前!会不会有装不下的可能性?不会因为不管哪一边的初始人数都不会>7个人,证明初始状态不会满员,转移状态也不应该满员!
接下来就是判定:
num==7||num==4||num==0时为可满足最终状态的合法状态。
转移就是记录一条通道经过的人数以及代价就行了。
最终的dp函数定义成通道经过的人的个数,知道前一个通道经过的人数和当前房屋的人数。
方便处理可以将7定义为”0”,0-6就是左向流动,8-14就是右向流动。

Gift

keywords: 工人 刷 POJ

思考

这道题相对简单一点,就是推理好了可以证明单调队列可做,否则没推完整或者推错了就成斜率优化了(虽然都解得出来)。
dp[i][j]表示前i个人装饰前j个单位能得到的最大魅力度。
dp[i][j]=max(dp[i1][k]+(jk)w);(k+1<=<=j)
经过变形,可以得到dp[i][j]=max(dp[i1][k]kw)+jw,对于每一个dp[i][j]来说,j是常量,而k是变量,故将dp[i1][k]kw部分求max,而且根据条件,k是满足条件的连续长度内的数。
然后发现我们其实是O(nm)的复杂度,每次枚举i,那么wi也是固定值了。所以就没有必要讨论i的情况,直接讨论k的单调性就行了。

混合维度背包

keyword:背包 DP1

思考

拿给Doggu做貌似都没有解出来……给了提示后貌似有了思路。其实我出这道题的目的很简单。就是探寻背包的特点。背包的突破点有很多(别说二进制了……),这次的W之积也是一种。很明显的线索,但是不认真看还真对这个线索摸不着头脑。尝试按照HINT说说将vi乘起来发现貌似没什么帮助?其实复杂度的提示已经说明了一切。O(nm),之不过m变了而已,一模一样的01背包,但是却不好做了?
NOIP的题就是应该这么出,什么码农题还是放在省选吧,靠算法灵活性才是培养一个走得远的OIer必要的素质。

101->010

keywords: atcoder 转移类神题

思考

最近都在研究各种神奇的DP状态定义,忽视了转移的巧妙啊!
一串01串,询问最多几次能将101变成010,(替换后能够继续替换!),贪心连样例都过不了系列……
核心code

cin>>n>>s;s="0"+s;for(int i=3;i<s.size();i++){    dp[i]=dp[i-1];    if(s.substr(i-2,3)=="101"){        l=i;        for(int j=i-2;j>0&&s[j]!='0';j--)            dp[i]=max(dp[i],dp[j-1]+i-j-1);    }    else if(s[i]=='0')l=0;    if(l)dp[i]=max(dp[i],dp[l-3]+i-l+1);}

有一些疑惑,大致上是定义的到i位最多的骚操作的个数,转移则是迷一样的原因是这样的对于11011111111011明显需要不同的策略,那么这种会使贪心大爆炸的范例却可以通过判定处理完101之前的1的个数来进行优化。那么dp[i]的转移就很简单了,
1.继承
2.经行一次change
3.放弃此次chance
而放弃的当前不优结果可以通过未来状态重新计算,因为位数就在那3步之内反悔有效,所以这就是YYR将的基于未来状态的DP!

非DP,二分图

keywords :atcoder Atcoder CODE FESTIVAL 2017 B C

虽然这道题也是三步啊
那么这道巧妙的题这么做?染色的技巧的确很好,推出通式的过程还是不容易啊……我个蒟蒻。

然后就是传说的并查集做法,并查集处理好元素的颜色?没有,直接合并。正确性?关注这篇blog吧,很详细,就不做不必要的补充了:

here 感谢blog主

这里写图片描述

原创粉丝点击