八数码问题
这是迄今为止,除数独外最吸引我的问题。采用宽度搜索方法。
问题描述:
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某个数字。棋盘中留有一个空格,空格用0表示。空格周围的棋子可以移动到空格中。给出一种初始布局(初始状态)和目标布局,找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
编程思路:
1、建立保存链表结构的类,包括layer(层次)、father(父亲)和sun(儿子)。
2、建立基础数据表,确定空格每一种状态(位置)能够移动(变化)到下一个状态(位置)的信息表,移动的方式有四种,上、下、左、右移动一格(0与该数字互换),不能移出边界。
3、建立一个函数,根据一个状态列表生成下一个状态(多态)的多个列表。
4、为防止状态逆向变化,进行去重处理,确保状态无重复。
5、找到目标状态后,通过逆向搜根,获取各中间状态列表。
start = [7, 2, 3, 1, 6, 4, 8, 0, 5]
# start = [2, 8, 3, 1, 6, 4, 7, 0, 5]
end = [1, 2, 3, 8, 0, 4, 7, 6, 5]
# 记录空格(0)从一个状态(位置)变化到下一个状态(位置)信息
base = [[0, [1, 3]], [1, [0, 2, 4]], [2, [1, 5]], [3, [0, 4, 6]], [4, [1, 3, 5, 7]],
[5, [2, 4, 8]], [6, [3, 7]], [7, [4, 6, 8]], [8, [5, 7]]]
sum_list = [] # 存放链表数据
print("start", start)
print("end", end)
class Lists: # 建立一个链表类,按层次保存状态列表
def __init__(self, layer, father):
self.layer = layer
self.sun = moving(father)
self.father = father
def moving(state): # 统计从一个状态(father)变化到下一个状态(sun)的所有列表
sun = []
zero_ind = state.index(0)
for b in base[zero_ind][1]:
te = copy.deepcopy(state)
te[b], te[zero_ind] = 0, te[b]
sun.append(te)
return sun
if __name__ == '__main__':
import time
import copy
t0 = time.time()
s = [start]
c = 1
result = []
while True:
for f in s:
L = Lists(c, f) # 实例化链表类
for g in L.sun:
if g == end:
print("成功!共搜索{}层。".format(c))
sum_list.append(L)
result.append(end)
for i in range(c, 0, -1): # 逆向搜根
for pp in sum_list:
if pp.layer == i and (end in pp.sun):
result.append(pp.father)
end = pp.father
break
result.reverse()
for r in result:
print(r)
print("耗时{}s。".format(time.time()-t0))
exit()
for a in sum_list: # 去重,关键环节
if a.layer == c-1 and a.father in L.sun:
L.sun.remove(a.father)
sum_list.append(L)
s = []
for i in sum_list:
if i.layer == c:
for ii in i.sun:
s.append(ii)
c += 1
if c > 20:
print("搜索层次超过设定值,失败!")
exit()
D:\Python\fang\venv\Scripts\python.exe D:/Python/study/20200908/test6.py
start [7, 2, 3, 1, 6, 4, 8, 0, 5]
end [1, 2, 3, 8, 0, 4, 7, 6, 5]
成功!共搜索15层。
[7, 2, 3, 1, 6, 4, 8, 0, 5]
[7, 2, 3, 1, 6, 4, 0, 8, 5]
[7, 2, 3, 0, 6, 4, 1, 8, 5]
[0, 2, 3, 7, 6, 4, 1, 8, 5]
[2, 0, 3, 7, 6, 4, 1, 8, 5]
[2, 6, 3, 7, 0, 4, 1, 8, 5]
[2, 6, 3, 0, 7, 4, 1, 8, 5]
[2, 6, 3, 1, 7, 4, 0, 8, 5]
[2, 6, 3, 1, 7, 4, 8, 0, 5]
[2, 6, 3, 1, 0, 4, 8, 7, 5]
[2, 0, 3, 1, 6, 4, 8, 7, 5]
[0, 2, 3, 1, 6, 4, 8, 7, 5]
[1, 2, 3, 0, 6, 4, 8, 7, 5]
[1, 2, 3, 8, 6, 4, 0, 7, 5]
[1, 2, 3, 8, 6, 4, 7, 0, 5]
[1, 2, 3, 8, 0, 4, 7, 6, 5]
耗时4.986737966537476s。
Process finished with exit code 0