【省选组】模拟 gmoj 3980. 推箱子
经典的推箱子是一个来自日本的古老游戏,目的是在训练你的逻辑思考能力。在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的利用有限的空间和通道,合理安排移动的次序和位置,才能顺利的完成任务。
这个游戏有一个相对简单的版本,就是只有一个木箱,要将其推到一个确定的目标位置。举个例子:
..#@.
.X.O.
##..#
其中“.”表示没有障碍的格子,“#”表示有障碍的格子,“X”表示目标位置(注意这个格子是没有障碍的),“O”是箱子(对于人来说箱子存在的格子是不能越过的),“@”是人的位置。注意上面这个情况是可以将箱子推到目标点去的,因为人只要向右一格,向下一格,然后推着箱子向左走两格,就完成了任务。
而下面这个例子是无解的:
..#..
.X.O.
##.@#
现在我们的主人公想知道,对于一个给定的地图(与上面两个不同的是没有了箱子和人的初始位置),有多少种箱子和人的初始摆放方法(箱子的初始位置和人的初始位置和目标位置必须两两不同)能够使得箱子能被人成功地推到目标位置。
这题真nm恶心
做法的话oj上的题解已经非常详细了,但我还是用自己的话说一下。
我们可以将箱子从终点开始反推,记录当前箱子位置和人在箱子的哪一侧。
然后就是维护的问题。
第一:
判断人可不可以从箱子的这一边走到另一边,即判断两个点在不经过某一个点情况下是否连通。
这个可以直接判断是不是在同一个点双里就行,但是因为一个点可能会在多个点双里所以我不会维护,用了题解的做法。
下面贴上题解:
1:x和y都不是z的后代,那么一定联通
2:x和y有一个是z的后代,一个不是,一般性不妨设x 不是z的后代,那么如果low[vy(表示y所在的那个子树)]<dfn[z],x和y联通
3:x和y是z的后代,并且他们在一颗子树中(vx==vy),那么连通。
4:x和y是z的后代,low[vx]<dfn[z]&&low[vy]<dfn[z],那么连通。
第二:
判断在不经过某个点的情况下一个点与多少个点连通。
我也是用的题解做法。。
还是贴上题解:
1:x不是y的后代,那么除了那些low[vi]>=dfn[y]的子树中的点到达不了,其他点(除了y)都能到达。
2:x是y的儿子vi的后代并且low[vi]<dfn[y],那么除了那些low[vi]>=dfn[y]的子树中的点到达不了,其他点(除了y)都能到达。
3:x是y的儿子vi的后代并且low[vi]>=dfn[y],那么能够到达vi子树中的点。
这道题就这么结束了,但是细节真的挺多的。