学习在单向运动中做区间闭包,以及把带胜负、和棋、最快获胜/最慢失败规则的游戏统一成有限状态图逆推。
前置:区间排序、BFS、博弈图、拓扑式逆推。
《火车站》的转乘路径数可以指数多,《过河卒》又允许在状态图中循环而产生和棋。直接搜索单条路径都会被重复状态淹没。正确对象是不动点闭包:前者不断扩张单调可达区间,后者从终局反向扩张必胜/必败吸引域。
向右时,初始可达位置为 x。所有左端点不超过当前最远位置的线路都能在某个已到达站换入;若其右端大于 x,它的右端可成为停靠结果,并可能扩张闭包。按左端点扫描每条线路一次。向左对称地按右端点降序扫描。
归纳扫描前所有不超过边界的站可达;新线路与可达区间相交,可在交点换入并沿同方向到端点。反之左端点尚超过边界的线路没有可换乘站,不能提前进入。复杂度 $O(m\log m)$。
right = x
for intervals ordered by left endpoint while left <= right:
if interval.right > x: record interval.right
right = max(right, interval.right)
repeat symmetrically toward left
output sorted distinct recorded endpoints
枚举所有合法位置三元组与轮次,计算出度并初始化终局:黑到第一行、黑红重合、当前无合法步。用按距离的小根堆逆推。弹出必败状态时,未知前驱立即成为必胜;弹出必胜状态时,令前驱未确认后继数减一,全部后继均必胜后前驱成为必败,距离取最大后继加一。剩余未知为和。
这正是有限零和完全信息博弈的吸引域定义。小根堆保证必胜状态第一次由距离最小的必败后继确定;必败等待全部后继后取最大,符合双方题面策略。
状态 $O(S^3)$、边转移常数,其中可通行格 $S\le100$;内存约百万状态数组。
initialize terminal WIN/LOSS states with distance 0
priority_queue ordered by distance
while queue:
state = pop()
for predecessor p generated on demand:
if state is LOSS: mark p WIN with distance+1
else:
remaining_successors[p] -= 1
record maximum winning-successor distance
if remaining becomes 0: mark p LOSS with max+1
unknown states after propagation are draws
《火车站》将向右与向左完全分开,排序后每条线路只进入扫描指针一次;结果端点要排序去重。《过河卒》对两枚同质红棋的位置始终排序,以唯一编码压缩状态;必胜前驱在看到第一个必败后即可确定,必败前驱则必须等全部后继确定为必胜,两者的距离 min/max 不得混用。
火车站是单调可达闭包,过河卒是胜负吸引闭包;两者都从已知集合反复加入满足局部条件的新对象,直到不动点。
火车站与显式区间图 BFS 对拍;过河卒在 $3\times3$ 棋盘显式建全反图,对拍按需前驱版本。