闲着没事用回溯法写了个解水排序谜题的Python代码,这里分享给大家,代码比较粗糙。
在数据定义部分,矩阵每一行是一个水瓶,从左到右表示从瓶底到瓶口的颜色。
输出结果(a -> b)表示按顺序从a瓶倒入b瓶。
import copy
from collections import Counter
class WaterSort(object):
def __init__(self, shuiguan):
self.shuiguan_origin = shuiguan # 原始水管
self.shuiguan_current = copy.deepcopy(self.shuiguan_origin) # 当前水管
self.visited = [] # 试过的失败操作
self.orderList = [] # 当前操作
self.orderflag = 0 # 是否存在有效操作
def check_color(self, x):
# 检查x中是否颜色相同
d = dict(Counter(x))
if len(d) <= 1:
return 1
else:
return 0
def check_complete(self):
# 检查是否排序完成
for shuiguan in self.shuiguan_current:
if len(shuiguan) == 0:
continue
elif len(shuiguan) < 4:
return 0
else:
if self.check_color(shuiguan) == 0:
return 0
return 1
def order(self, o):
# 执行操作o:(a,b),由a倒入b
while 1:
if len(self.shuiguan_current[o[0]]) == 0:
break
if len(self.shuiguan_current[o[1]]) == 0:
self.shuiguan_current[o[1]].append(self.shuiguan_current[o[0]][-1])
del self.shuiguan_current[o[0]][-1]
elif len(self.shuiguan_current[o[1]]) < 4 and self.shuiguan_current[o[0]][-1] == \
self.shuiguan_current[o[1]][-1]:
self.shuiguan_current[o[1]].append(self.shuiguan_current[o[0]][-1])
del self.shuiguan_current[o[0]][-1]
else:
break
def sort(self):
shuiguan_visited = []
shuiguan_visited.append(copy.deepcopy(self.shuiguan_current))
print(self.shuiguan_current)
while self.check_complete() == 0:
self.orderflag = 0
for i in range(len(self.shuiguan_current)):
# i被倒水管
if len(self.shuiguan_current[i]) == 4:
# 被倒水管满
continue
for j in range(len(self.shuiguan_current)):
# j倒出水管
# 即j倒i
if j == i or len(self.shuiguan_current[j]) == 0:
# 同一水管或倒出水管空
continue
if len(self.shuiguan_current[i]) == 0 and self.check_color(self.shuiguan_current[j]):
# 被倒水管空且倒出水管颜色相同
continue
remainLen = 4 - len(self.shuiguan_current[i]) # 水管剩余长度
if len(self.shuiguan_current[j]) > remainLen and self.check_color(
self.shuiguan_current[j][(-remainLen - 1):]):
# 如果j倒入i后仍剩余倒出颜色
continue
self.orderList.append((j, i)) # 执行倒水操作
if self.orderList in self.visited:
self.orderflag = 0
self.orderList = self.orderList[:-1] # 回退一步
continue
if len(self.shuiguan_current[i]) == 0:
self.order((j, i)) # 倒水
print(self.shuiguan_current)
if self.shuiguan_current in shuiguan_visited:
self.orderflag = 0
# 如果返回之前的状态,则操作无效
self.visited.append(copy.deepcopy(self.orderList)) # 记录无效操作
self.orderList = self.orderList[:-1] # 回退一步
# 水管状态回退
self.shuiguan_current = copy.deepcopy(self.shuiguan_origin)
for o in self.orderList:
self.order(o)
print(self.shuiguan_current)
# continue
else:
self.orderflag = 1
shuiguan_visited.append(copy.deepcopy(self.shuiguan_current))
# break
elif len(self.shuiguan_current[i]) < 4 and self.shuiguan_current[i][-1] == self.shuiguan_current[j][
-1]:
self.order((j, i)) # 倒水
print(self.shuiguan_current)
if self.shuiguan_current in shuiguan_visited:
self.orderflag = 0
# 如果返回之前的状态,则操作无效
self.visited.append(copy.deepcopy(self.orderList)) # 记录无效操作
self.orderList = self.orderList[:-1] # 回退一步
# 水管状态回退
self.shuiguan_current = copy.deepcopy(self.shuiguan_origin)
for o in self.orderList:
self.order(o)
print(self.shuiguan_current)
# continue
else:
self.orderflag = 1
shuiguan_visited.append(copy.deepcopy(self.shuiguan_current))
# break
else:
# i不空是管且颜色不可倒
self.orderflag = 0
self.visited.append(copy.deepcopy(self.orderList)) # 记录无效操作
self.orderList = self.orderList[:-1] # 回退一步
if self.orderflag == 1:
break
if self.orderflag == 0:
# 目前操作死掉
self.visited.append(copy.deepcopy(self.orderList))
temp = copy.deepcopy(self.visited)
self.visited = []
for vis in temp:
if len(vis) > len(self.orderList) and vis[:len(self.orderList)] == self.orderList:
pass
else:
self.visited.append(vis)
self.orderList = self.orderList[:-1] # 回退一步
self.shuiguan_current = copy.deepcopy(self.shuiguan_origin)
for o in self.orderList:
self.order(o)
print(self.shuiguan_current)
else:
self.orderflag = 0
for o in enumerate(self.orderList):
# print(o)
print(o[0], ': (', o[1][0] + 1, '->', o[1][1] + 1, ')')
if __name__ == '__main__':
shuiguan = [[],
[],
['m', 'r', 'r', 't'],
['p', 'g', 'h', 'p'],
['h', 'y', 'y', 'g'],
['m', 'o', 'o', 'g'],
['m', 'y', 'p', 'h'],
['t', 'p', 'b', 'o'],
['b', 't', 'h', 'r'],
['b', 'y', 'o', 'b'],
['t', 'm', 'r', 'g']]
d = {}
for i in shuiguan:
for j in i:
try:
d[j] += 1
except:
d[j] = 1
for key in d:
if d[key] != 4:
print('颜色矩阵有误,请检查!!!')
ws = WaterSort(shuiguan)
ws.sort()