在宽度优先搜索算法解决八数码问题的基础上添加估价函数,选取哈密尔顿距离为h(n)
import copy
import numpy as np
from datetime import datetime
# 字符串列表化
def string_to_ls(str):
return [i.split(' ') for i in str.split(',')]
# 获取位置
def get_loacl(arr, target):
# r, c = np.where(arr == target)
# return r, c
for i in arr:
for j in i:
if j == target:
return arr.index(i), i.index(j)
# 获取可以和0交换位置的元素
def get_elements(arr):
r, c = get_loacl(arr, '0')
elements = []
if r > 0:
elements.append(arr[r - 1][c]) # 上面的元素
if r < 2:
elements.append(arr[r + 1][c]) # 下边的元素
if c > 0:
elements.append(arr[r][c - 1]) # 左面的元素
if c < 2:
elements.append(arr[r][c + 1]) # 右面的元素
return elements
def get_child(arr, e):
# 深拷贝与浅拷贝!!
arr_new = copy.deepcopy(arr)
r, c = get_loacl(arr_new, '0')
r1, c1 = get_loacl(arr_new, e)
arr_new[r][c], arr_new[r1][c1] = arr_new[r1][c1], arr_new[r][c]
return arr_new
# 哈密尔顿距离
def get_distance(arr1, arr2):
distance = []
for i in arr1:
for j in i:
loc1 = get_loacl(arr1, j)
loc2 = get_loacl(arr2, j)
distance.append(abs(loc1[0] - loc2[0]) + abs(loc1[1] - loc2[1]))
return sum(distance)
def is_goal(arr, goal):
return arr == goal
class state:
def __init__(self, state, deep, parent, distance):
# state是一个3x3的ls矩阵
self.state = state
self.deep = deep
self.parent = parent
self.distance = distance
def chidren(self):
chidren = []
for i in get_elements(self.state):
child = state(state=get_child(self.state, i),
deep=self.deep + 1,
parent=self,
distance=self.deep + 1 + get_distance(self.state, goal_arr))
chidren.append(child)
return chidren
# 打印求解路径
def print_path(n):
if n.parent == None:
return
else:
print('↑')
print(np.array(n.parent.state))
print_path(n.parent)
if __name__ == '__main__':
# initial = '0 1 3,4 2 5,7 8 6'
# goal = '4 1 3,7 0 5,8 2 6'
initial = '4 0 1,6 8 5,7 3 2'
goal = '5 8 2,1 0 4,6 3 7'
initial_arr = string_to_ls(initial)
goal_arr = string_to_ls(goal)
initial_arr = state(initial_arr, deep=0, parent=None, distance=get_distance(initial_arr, goal_arr))
start = datetime.now()
open = [initial_arr]
close = []
# limit = eval(input('请输入要搜索的深度:'))
limit = 19
while len(open) > 0:
open_tb = [i.state for i in open]
close_tb = [i.state for i in close]
n = open.pop(0)
close.append(n)
if is_goal(n.state, goal_arr):
print(np.array(n.state))
print_path(n)
print('--' * 20)
print('成功搜索到路径,求解过程如上')
break
else:
if n.deep < limit:
for i in n.chidren():
if i.state not in open_tb:
if i,state not in close_tb:
open.insert(0, i)
open.sort(key=lambda x: x.distance)
else:
print('该深度下无解')
end = datetime.now()
print('--' * 20)
print('限制深度为:{}\t搜寻深度为:{}\n启发式A算法搜索步数为:{}'.format(limit, close[-1].deep, len(close) - 2))
print('--' * 20)
print('搜索耗时:', end - start)