简要题意:
给定一个 3 × 3 3 \times 3 3×3 的矩阵,每次可以把空格旁边(四方向)的一个位置移到空格上。求到目标状态的最小步数。
前置知识:
OK \text{OK} OK,现在我们来考虑双向宽搜。
假设 A A A 和 B B B 两个人被困在了迷宫的两个角落,现在他们首先要互相找到对方;他们都会分身术。你认为下面哪一种方法最快:
-
A A A 主动分身去各个路口分支找 B B B, B B B 原地待命。
-
B B B 主动分身去各个路口分支找 A A A, A A A 原地待命。
-
A A A 和 B B B 同时分身去各个路口分支找对方。
无可厚非是最后一种方法最快。但请不要误解:现实生活中我们提倡前两种方案,因为现实中没有人会分身的。
诚然,互相找的效率是最高的。可是你可能会问了:
假设一共 4 4 4 步找到对方,两人各走 2 2 2 步和一个人找 4 4 4 步不是一样的吗?
粗想一下,确实如此。但是在 爆炸性指数级的压力 之下,完全不同。
就在这个问题的基础上,假设每走 1 1 1 步都有 4 4 4 种选法(即四方向)。
那么,一个人找的时间是 4 4 = 256 4^4 = 256 44=256.
两个人同时找对方的时间是 4 2 + 4 2 = 32 4^2 + 4^2 = 32 42+42=32.
数据说明,快了 8 8 8 倍。这单是 4 4 4 步就快了 8 8 8 倍!
经过粗略的计算,假设一共要走 20 20 20 步的话,双向找比单向快 524288 524288 524288 倍,约 5.2 × 1 0 5 5.2 \times 10^5 5.2×105,假设时间限制是 1 s 1s 1s 的话,显然这两个程序的分数是有着极大差异的!
这是因为,双向搜索在本质上把步数减半了,而 在指数上减半会让幂大大降低,因此双向搜索会更快。
那么双向搜索适用于哪些题目呢?
- 明确知道起点和终点的。比方说这种题(现编的):
对于已知的一个数,每次可以将其连续 k 个数字同时 +1.
求让它至少有 p 位连续相同的步数。
显然,终点不明确,无法搜索。你不可能把所有的终点都枚举一遍。
- 明确知道搜索深度的。即明确知道多少步会走到。比方说 埃及分数:
将一个分数分解为若干分数的和。有一些分母不能使用。
显然,你不知道会分解成多少个分数。因此本题需要使用 迭代加深搜索(IDDFS) 而非 bfs \text{bfs} bfs.
然后,那你会问了:八数码这一题,我也不知道最多会有多少步呀?
-
那么,你不会自己随机造吗?
-
我怎么造啊?
-
用随机种子搞一个 0 0 0 ~ 8 8 8 的任意排列,然后取出最大答案啊
-
我连 std \text{std} std 都不会写啊
哦!对。本题你可以稍微分析一下,你会发现,既然肯定能走到,你的