数据结构(三十一)
学习数据结构与算法过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
—— 八数码难题 ——
1.题目描述
八数码问题也称为九宫问题。在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格,与空格相邻的棋子可以移到空格中。要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始状态转变成目标状态的移动棋子步数最少的移动步骤。
代码
使用算法:启发式搜索算法
使用广度搜索算法求解点击这里
python
import copy
import numpy as np
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)
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 = '2 8 3,1 6 4,7 0 5'
goal = '1 2 3,8 0 4,7 6 5'
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))
open = [initial_arr]
close = []
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)
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('无解')
print('搜索步数为:',len(close) - 2)