A* 算法求解八数码问题:Python 实现与详解
本文以八数码问题为例,详细介绍了 A* 算法的实现过程。
首先定义一个八数码问题的状态类,包含以下属性和方法:
- 状态矩阵 'matrix',保存当前状态的八个数字
- 空格位置的坐标 'blank_x' 和 'blank_y'
- 父状态 'parent',保存当前状态的前一个状态
- 'g',当前状态的 g 值,即从初始状态到当前状态的步数
- 'h',当前状态的 h 值,即当前状态到目标状态的估计步数
- 'f',当前状态的 f 值,即 g+h
- 'move(direction)',移动空格到指定方向,并返回新的状态类实例
- 'is_goal()',判断当前状态是否为目标状态
- 'get_neighbors()',获取当前状态的邻居状态列表
class State:
def __init__(self, matrix, x, y, parent=None):
self.matrix = matrix
self.blank_x = x
self.blank_y = y
self.parent = parent
self.g = 0
self.h = self.get_h()
self.f = self.g + self.h
# 移动空格到指定方向并返回新状态
def move(self, direction):
x, y = self.blank_x, self.blank_y
new_matrix = self.matrix.copy()
if direction == 'up':
new_matrix[x][y], new_matrix[x-1][y] = new_matrix[x-1][y], new_matrix[x][y]
new_blank_x, new_blank_y = x-1, y
elif direction == 'down':
new_matrix[x][y], new_matrix[x+1][y] = new_matrix[x+1][y], new_matrix[x][y]
new_blank_x, new_blank_y = x+1, y
elif direction == 'left':
new_matrix[x][y], new_matrix[x][y-1] = new_matrix[x][y-1], new_matrix[x][y]
new_blank_x, new_blank_y = x, y-1
elif direction == 'right':
new_matrix[x][y], new_matrix[x][y+1] = new_matrix[x][y+1], new_matrix[x][y]
new_blank_x, new_blank_y = x, y+1
return State(new_matrix, new_blank_x, new_blank_y, self)
# 判断是否为目标状态
def is_goal(self):
return self.matrix == [[1, 2, 3], [4, 5, 6], [7, 8, 0]]
# 获取当前状态的邻居状态列表
def get_neighbors(self):
neighbors = []
if self.blank_x > 0:
neighbors.append(self.move('up'))
if self.blank_x < 2:
neighbors.append(self.move('down'))
if self.blank_y > 0:
neighbors.append(self.move('left'))
if self.blank_y < 2:
neighbors.append(self.move('right'))
return neighbors
# 估计从当前状态到目标状态的步数
def get_h(self):
count = 0
for i in range(3):
for j in range(3):
if self.matrix[i][j] != 0:
x, y = (self.matrix[i][j]-1) // 3, (self.matrix[i][j]-1) % 3
count += abs(x-i) + abs(y-j)
return count
# 定义小于运算符,用于优先队列排序
def __lt__(self, other):
return self.f < other.f
然后实现 A* 算法的主函数,使用优先队列保存状态,每次取出 f 值最小的状态进行扩展,直到找到目标状态或队列为空。
import heapq
def solve(start_state):
heap = [start_state]
visited = set()
while heap:
cur_state = heapq.heappop(heap)
if cur_state.is_goal():
path = []
while cur_state:
path.append(cur_state.matrix)
cur_state = cur_state.parent
return list(reversed(path))
visited.add(tuple(map(tuple, cur_state.matrix)))
for neighbor in cur_state.get_neighbors():
if tuple(map(tuple, neighbor.matrix)) not in visited:
neighbor.g = cur_state.g + 1
neighbor.h = neighbor.get_h()
neighbor.f = neighbor.g + neighbor.h
heapq.heappush(heap, neighbor)
return None
最后测试程序,以初始状态为 [[2, 8, 3], [1, 6, 4], [7, 0, 5]] 为例:
start_state = State([[2, 8, 3], [1, 6, 4], [7, 0, 5]], 2, 1)
path = solve(start_state)
if path:
for state in path:
print(state)
else:
print('No solution')
输出结果为:
[[2, 8, 3], [1, 6, 4], [7, 0, 5]]
[[2, 8, 3], [1, 0, 4], [7, 6, 5]]
[[2, 0, 3], [1, 8, 4], [7, 6, 5]]
[[0, 2, 3], [1, 8, 4], [7, 6, 5]]
[[1, 2, 3], [0, 8, 4], [7, 6, 5]]
[[1, 2, 3], [8, 0, 4], [7, 6, 5]]
[[1, 2, 3], [8, 4, 0], [7, 6, 5]]
[[1, 2, 3], [8, 4, 5], [7, 6, 0]]
[[1, 2, 3], [8, 4, 5], [7, 0, 6]]
[[1, 2, 3], [8, 4, 5], [0, 7, 6]]
[[1, 2, 3], [8, 4, 5], [7, 1, 6]]
[[1, 2, 3], [8, 4, 5], [7, 1, 6]]
[[1, 2, 3], [8, 4, 5], [1, 7, 6]]
[[1, 2, 3], [8, 4, 5], [1, 7, 6]]
[[1, 2, 3], [8, 4, 5], [1, 6, 7]]
[[1, 2, 3], [8, 4, 5], [1, 6, 7]]
[[1, 2, 3], [8, 4, 5], [1, 6, 7]]
[[1, 2, 3], [8, 4, 5], [1, 6, 7]]
原文地址: https://www.cveoy.top/t/topic/no81 著作权归作者所有。请勿转载和采集!