# 描述
# 在九宫格里放在1到8共8个数字还有一个是空格,与空格相邻的数字可以移动到空格的位置,问给定的状态最少需要几步能到达目标状态(用0表示空格):
# 1 2 3
# 4 5 6
# 7 8 0
#
# 输入
# 输入一个给定的状态。
#
# 输出
# 返回True 或 False
1.BFS
Primeras definiciones se almacenan nodo "estado"
from copy import deepcopy
import numpy as np
class Node:
def __init__(self, state, parent, operator):
self.state = state
self.parent = parent
self.operator = operator
def operate(self, dir): # 返回算符变换后的新节点
new_state = move0(self.state, dir)
if new_state == False:
return None
else:
return Node(new_state, self, dir) # 以self为父
def traverse(self):
cur = self
res = []
while cur is not None:
print(cur.state)
res.append(cur)
cur = cur.parent
return res
def depth(self):
return len(self.traverse()) - 1
Dos funciones auxiliares
def pprint(arr):
print(np.array(arr))
def find0(state): # 在state中寻找0的位置
for i in range(len(state)):
for j in range(len(state)):
if state[i][j] == 0:
ind0 = [i, j]
return ind0
operación, la dirección de movimiento 0 espacio de dirección, y devuelve el nuevo estado definido por el operador
dirs = ['up', 'down', 'left', 'right']
def move0(state, direction): # state当前状态,2d list,dir为0的移动方向
state1 = deepcopy(state)
ind0 = find0(state1)
x, y = ind0[0], ind0[1] # 0的当前位置
if direction == 'up':
if x == 0:
return False
else:
tempind = [x-1, y] # 待交换的位置
# state[x][y], state[x-1,y] = state[x-1][y], state[x][y]
state1[x][y] = state1[x - 1][y]
state1[x - 1][y] = 0
# print(state)
elif direction == 'down':
if x == len(state1) - 1: # 如果x在最后一行
return False
else:
tempind = [x+1, y]
state1[x][y] = state1[x + 1][y]
state1[x + 1][y] = 0
elif direction == 'left':
if y == 0:
return False
else:
tempind = [x, y-1]
state1[x][y] = state1[x][y - 1]
state1[x][y - 1] = 0
elif direction == 'right':
if y == len(state1) - 1:
return False
else:
tempind = [x, y+1]
state1[x][y] = state1[x][y + 1]
state1[x][y + 1] = 0
return state1
La siguiente es una función de búsqueda en anchura BFS, BFS es lo escribí yo mismo, bfs1 nodo se define de acuerdo con el libro escrito
stack = []
def bfs(state,goal): # 不定义结点的版本
open = []
closed = []
open.append(state)
while True:
print(f'open: {len(open)}')
if not open: # open为空
return False
n = open.pop(0) # 队列先进先出fifo, n为open表中第一个结点
closed.append(n)
for dir in dirs:
next_state = move0(n, dir)
if next_state is not False and next_state not in closed: # 下一个状态在状态空间内且未被搜索过
open.append(next_state)
if next_state == goal:
pprint(next_state)
return True
pprint(next_state)
print()
def bfs1(init_state,goal): # 按照书上的节点定义
open = []
closed = []
init_node = Node(init_state, None, None)
open.append(init_node)
while True:
if not open: # open是空表
return False
node = open.pop(0) # 把第一个节点node弹出
closed.append(node) # 将node放入closed表
for dir in dirs:
node_new = node.operate(dir)
if node_new is not None and node_new not in closed: # 下一个状态在状态空间内且未被搜索过
open.append(node_new)
if node_new.state == goal:
pprint(node_new.state)
nodelist = node_new.traverse()
nodelist.reverse()
print()
[(print(node.operator), pprint(node.state)) for node in nodelist]
return True
pprint(node_new.state)
print()
Por ejemplo prueba
goal = [[1, 2, 3],
[8, 0, 4],
[7, 6, 5]]
init = [[2,8,3],
[1,0,4],
[7,6,5]]
if __name__ == '__main__':
print(bfs1(init,goal))
"""
out:
None
[[2 8 3]
[1 0 4]
[7 6 5]]
up
[[2 0 3]
[1 8 4]
[7 6 5]]
left
[[0 2 3]
[1 8 4]
[7 6 5]]
down
[[1 2 3]
[0 8 4]
[7 6 5]]
right
[[1 2 3]
[8 0 4]
[7 6 5]]
True
"""
2.DFS
def dfs(init_state, goal):
initnode = Node(init_state, None, None) # 初始结点
open = [] # 栈, 已探索但未展开的结点
closed = []
open.append(initnode)
while True:
if not open: # 若open为空
print('此初始状态无法完成搜索。')
return False
curnode = open.pop()
closed.append(curnode.state)
if curnode.depth() > 5:
continue
for dir in dirs:
node = curnode.operate(dir)
if node is not None and node.state not in closed: # node在状态空间内,且未被探索过
open.append(node)
if node.state == goal: # 已搜索到
print('搜索成功。')
# print(node.state, goal)
nlist = node.traverse()
nlist.reverse()
# print(nlist)
for n in nlist: # 输出
# print(n)
print(n.state) if n.operator is None else print(n.operator, n.state)
return True
print(node.state)
Resumen: La única diferencia es que DFS y BFS, mesa DFS es una pila de abierta, y el BFS mesa abierta para la cola