归纳几个蛮不错的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[i−1][k]+(j−k)∗w)
;
(k+1<=原始位置<=j)
经过变形,可以得到
dp[i][j]=max(dp[i−1][k]−k∗w)+j∗w
,对于每一个
dp[i][j]
来说,j是常量,而k是变量,故将
dp[i−1][k]−k∗w
部分求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位最多的骚操作的个数,转移则是迷一样的原因是这样的对于
1101111
与
1111011
明显需要不同的策略,那么这种会使贪心大爆炸的范例却可以通过判定处理完101之前的1的个数来进行优化。那么dp[i]的转移就很简单了,
1.继承
2.经行一次change
3.放弃此次chance
而放弃的当前不优结果可以通过未来状态重新计算,因为位数就在那3步之内反悔有效,所以这就是YYR将的基于未来状态的DP!
非DP,二分图
keywords :atcoder Atcoder CODE FESTIVAL 2017 B C
虽然这道题也是三步啊!
那么这道巧妙的题这么做?染色的技巧的确很好,推出通式的过程还是不容易啊……我个蒟蒻。
然后就是传说的并查集做法,并查集处理好元素的颜色?没有,直接合并。正确性?关注这篇blog吧,很详细,就不做不必要的补充了: