P4042 [AHOI2014/JSOI2014] 骑士游戏

原题

非常好的一道题,用到了一个重要的思路:消除dp的后效性

不要觉得这个东西很恐怖,其实这个东西并不复杂,只是名字有点吓人

我们容易想到对把原题抽象成一个图,我们容易想到如果该图为DAG我们要怎么做,直接拓扑上dp即可

但回到原题,我们发现dp就有了一些问题:这个题是有环的,我们对于一个环上的dp我们无法知道先更新哪一个值,换言之这个dp是有后效性的。

但我们同时也想到在这个环上一直绕,对答案来说一定是不优的(这里只是感性理解),但我们并不知道这个绕的策略是什么,因此这个问题让我们很难办

这里有一个重要的思路:消除dp后效性的方法:

  1. 先计算部分信息,再通过其他的dp加加减减,合并到当前信息去:换根dp就是这个思路

  2. 如果对于一个dp出现如果dpu更新dpv,则dpv更新dpu绝对不优,则我们改变dp顺序,再直接dp

这题用的是第二个思路

我们写出dp柿子,设dpu表示杀死u点怪兽消耗的最少体力值:

容易得到递推:

dpu=min(Ku,Su+i=1Rudpvi)

我们发现什么,我们发现后面这个柿子就满足第二个方法,因为如果存在dpvidpu,则我们一定不会用dpvi来更新

因此我们让dpu值初始为Su,并把所有Ku的值放到一个堆中,每次用最小的dpu值去更新所有指向他的点的、满足dpudpvdp值。如果有一个点的dp值被更新完了,就把dpu放到堆中。这个做法是正确的

  1. 如果在dpu更新完之前使用了Ku更新其他的点,则说明更新dpu一定要用到Kudp值的点来更新,因此Ku<dpu,用dpu更新一定不优

  2. 如果在dpu更新完后放到了堆中,但使用了Ku更新其他的点,则说明Kudpu,同理

  3. 如果在dpu更新完后放入了堆中,且使用了dpu更新其他的点,则说明Kudpu,这么做也是不劣的

通过这三种情况,就可以说明这个做法是正确的

最终复杂度O(nlogn+Ri)

p.s.,其实这个思路就是跑dijkstra,在上面dp是同一个思路,但dijkstra的朴素复杂度为O(mlogm),但这个题可以保证每个点只在堆中出现一次,因此复杂度可以在包括n的复杂度

p.s.s,感谢xjk提供的解答,使用dijkstra上跑dp的前提是这个dp是有贪心性质的,否则需要使用spfa。,如这题如果把Su+dpvi改成Su+mindpvi,这样dijkstra显然就不太可做了。

p.s.s.s,此题中也有部分题解写spfa做法(而且还能过?),参考这里

posted @   FOX_konata  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示