题目 1426: [蓝桥杯][历届试题]九宫重排
问题分析
九宫格,一个空格,8个数字,给定初态、终态
找到初态变换到终态需要移动的最小步数
输出步数,如果不可达输出-1
解题思路
① 分解子问题
\[\left[ \begin{matrix} 1\quad2\quad3 \\ .\quad4\quad6 \\ 7\quad5\quad8 \\ \end{matrix} \right] \begin{cases} \left[ \begin{matrix} .\quad2\quad3 \\ 1\quad4\quad6 \\ 7\quad5\quad8 \\ \end{matrix} \right] \begin{cases} ... \\ ... \\ \end{cases} \\ \\ \left[ \begin{matrix} 1\quad2\quad3 \\ 4\quad.\quad6 \\ 7\quad5\quad8 \\ \end{matrix} \right] \begin{cases} ... \\ ... \\ ... \\ ... \\ \end{cases}\\ \\ \left[ \begin{matrix} 1\quad2\quad3 \\ 7\quad4\quad6 \\ .\quad5\quad8 \\ \end{matrix} \right] \begin{cases} ... \\ ... \\ \end{cases} \end{cases} \]② 是否具有最优子结构
具有,但不好描述子问题之间的关系(非线性=>一般需要设置访问记录表,如果是线性自然就不会重复)
③ 寻找最小步数的过程,即为逐层分解的过程出现的第一个解
使用广度优先搜索BFS
队列中存放九宫格的状态(字符串形式的九宫格)和从初态到达该状态所需的步数
访问记录字典中存放bool值
结束条件:当前状态与终态相同,输出步数
代码
from queue import Queue
start = input()
end = input()
def next_state(curr, i):
dr = [-1, 1, 0, 0]
dc = [0, 0, -1, 1]
bi = curr.index('.')
newr, newc = dr[i] + bi//3, dc[i] + bi%3
if 0 <= newr < 3 and 0 <= newc < 3:
ni = newr*3+newc
curr = list(curr)
curr[bi], curr[ni] = curr[ni], curr[bi]
return ''.join(curr)
return None
def bfs(start):
sq = Queue()
sq.put([start, 0])
visits = {}
while not sq.empty():
curr, step = sq.get()
for i in range(4):
if curr == end:
return step
next = next_state(curr, i)
if next and not visits.get(next):
visits[next] = True
sq.put([next, step + 1])
return -1
print(bfs(start))