八数码问题(再续)
参见八数码问题(续)
前面的程序还是存在问题。
其一,如果初始状态一步变化到目标状态,是不能获得最短路径的。
其二,内存开销比较多。
其三,表达不够精炼。
其四,对搜索层次没有规定,可能导致程序无法终止,或内存开销过大,异常退出。
有鉴于此,对程序再次进行修正。
# start = [7, 2, 3, 1, 6, 4, 8, 0, 5]
# end = [1, 2, 3, 8, 0, 4, 7, 6, 5]
start = [7, 2, 3, 1, 6, 4, 8, 0, 5]
end = [8, 1, 3, 5, 0, 4, 6, 7, 2]
# start = [7, 2, 3, 1, 6, 4, 8, 0, 5]
# end = [7, 2, 3, 1, 6, 4, 0, 8, 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, sum_list1 = [], [] # 存放链表数据
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
def solution(state): # 判断是否有解
ct = 0
for k in range(9):
if k != 0:
for j in range(k):
if state[j] != 0 and state[k] > state[j]:
ct += 1
return ct
def search(summary, tier, state): # 把某个层级所有状态列表汇总到一个列表
for f in state:
lis = Lists(tier, f) # 实例化链表类
for a in summary: # 去重,关键环节
if a.layer == tier - 1 and a.father in lis.sun:
lis.sun.remove(a.father)
summary.append(lis)
ss = []
for i in summary:
if i.layer == tier:
for ii in i.sun:
ss.append(ii)
return ss
def root(direction, layer, group): # 搜根
global middle, count
temp, m = [], middle
for i1 in range(layer, 0, -1):
for g in group:
if g.layer == i1 and (m in g.sun):
temp.append(g.father)
m = g.father
if direction == 1: # 正方向搜索时,完成后逆序输出
temp.reverse()
temp.append(middle)
for t in temp:
print(t)
count += len(temp)
if __name__ == '__main__':
import time
import copy
t0 = time.time()
c1, c2 = solution(start), solution(end)
if (c1 - c2) % 2 != 0:
print("无解!")
exit()
if end in moving(start):
print("成功!,共搜索1层。")
s, e = [start], [end]
c, count, middle = 1, 0, 0
while True:
list_order = search(sum_list, c, s) # 从开始状态向目标状态搜索
list_reverse = search(sum_list1, c, e) # 从目标状态向开始状态搜索
for r in sum_list:
for r1 in sum_list1:
if r.father == r1.father:
middle = r1.father # 搜到共同的中间结果
root(1, c, sum_list)
root(0, c, sum_list1)
print("成功!共搜索{}层。".format(count - 1))
print("耗时{}s。".format(time.time() - t0))
exit()
c += 1
if c > 15:
print("搜索层次超过设定值,失败!")
exit()
s, e = list_order, list_reverse
D:\Python\Python38\python.exe D:/Python/study/20200908/test10.py
start [7, 2, 3, 1, 6, 4, 8, 0, 5]
end [8, 1, 3, 5, 0, 4, 6, 7, 2]
[7, 2, 3, 1, 6, 4, 8, 0, 5]
[7, 2, 3, 1, 0, 4, 8, 6, 5]
[7, 0, 3, 1, 2, 4, 8, 6, 5]
[0, 7, 3, 1, 2, 4, 8, 6, 5]
[1, 7, 3, 0, 2, 4, 8, 6, 5]
[1, 7, 3, 8, 2, 4, 0, 6, 5]
[1, 7, 3, 8, 2, 4, 6, 0, 5]
[1, 7, 3, 8, 0, 4, 6, 2, 5]
[1, 0, 3, 8, 7, 4, 6, 2, 5]
[1, 3, 0, 8, 7, 4, 6, 2, 5]
[1, 3, 4, 8, 7, 0, 6, 2, 5]
[1, 3, 4, 8, 7, 5, 6, 2, 0]
[1, 3, 4, 8, 7, 5, 6, 0, 2]
[1, 3, 4, 8, 0, 5, 6, 7, 2]
[1, 3, 4, 8, 5, 0, 6, 7, 2]
[1, 3, 0, 8, 5, 4, 6, 7, 2]
[1, 0, 3, 8, 5, 4, 6, 7, 2]
[0, 1, 3, 8, 5, 4, 6, 7, 2]
[8, 1, 3, 0, 5, 4, 6, 7, 2]
[8, 1, 3, 5, 0, 4, 6, 7, 2]
成功!共搜索19层。
耗时0.3413248062133789s。
Process finished with exit code 0