原题链接:
参考资料:
POJ 3414 - Pots | 眈眈探求 POJ 3414 Pots【BFS】【图搜】 - it610.com
一 特别注意:
1. 每一种操作对应于一个子节点,并且该子节点具有多种状态,包括:
1.1 A瓶溶液体积
1.2 B瓶溶液体积
1.3 操作类型
1.4 步数
1.5 父节点
PS:将以上各状态存储在一个字典中,将该字典作为一个子节点。
二 代码实现:
## 本代码的节点是结构体
# https://exp-blog.com/algorithm/poj/poj3414-pots/
# https://www.it610.com/article/4935648.htm
import collections
def bfs(graph,A,B,C):
# 设置节点的初始信息
# s = graph
graph['a'] = 0 #瓶子a的初始值
graph['b'] = 0 #瓶子b的初始值
# graph['pre'] = -1 # 前一**
graph['step'] = 0 # 记录步数
graph['flag'] = None # 记录操作类型
graph['parent'] = None # 设置父节点
# 存储已访问过的节点
visited = set()
visited.add(str(graph['a']) + str(graph['b']))
# 关于队列的参数
front = 0
rear = 0
queue = []
queue.append(graph) #加入到队列中,作为当前节点
## 记录其父节点
# parent = []
# parent.append(graph)
## 开始处理
while len(queue) >0:
# 弹出节点
vertex = queue.pop(0)
if vertex['a']==C or vertex['b'] == C:
# return vertex,parent
return vertex
# 获取邻接点,共涉及6种操作,因此得到6个子节点(每一次操作对应于一个子节点)
for i in range(6):
nodes= {}
if i==0:
# 执行:对a加满
nodes['a'] = A # 加满瓶子a
nodes['b'] = vertex['b'] # 保持不变
nodes['flag'] = 0 # 操作类型
elif i == 1:
# 执行:对b加满
nodes['a'] = vertex['a'] # 保持不变
nodes['b'] = B # 加满瓶子b
nodes['flag'] = 1 # 操作类型
elif i == 2:
# 执行:对a清空
nodes['a'] = 0 # 清空a
nodes['b'] = vertex['b'] # 保持不变
nodes['flag'] = 2 # 操作类型
elif i == 3:
# 执行:对b清空
nodes['a'] = vertex['a'] # 保持不变
nodes['b'] = 0 # 清空b
nodes['flag'] = 3 # 操作类型
elif i == 4:
# 执行:将A倒入B
if vertex['a']+vertex['b'] > B:
nodes['a'] = vertex['a'] + vertex['b'] -B # a有剩余
nodes['b'] = B # b加满了
nodes['flag'] = 4 # 操作类型
else:
nodes['a'] = 0 # a倒空了
nodes['b'] = vertex['a'] + vertex['b'] # b未加满
nodes['flag'] = 4 # 操作类型
else:
# 执行:将B倒入A
if vertex['a'] + vertex['b'] > A:
nodes['a'] = A # a加满了
nodes['b'] = vertex['a'] + vertex['b'] -A # b有剩余
nodes['flag'] = 5 # 操作类型
else:
nodes['a'] = vertex['a'] + vertex['b'] # a未加满
nodes['b'] = 0 # b倒空了
nodes['flag'] = 5 # 操作类型
# 每循环一次,判断当前节点:1 是否已经访问过 2 否:加入到已访问,并加入队列中
if str(nodes['a']) + str(nodes['b']) not in visited:
# 记录操作步骤
nodes['step'] = vertex['step'] + 1
# 添加到已访问列表
visited.add(str(nodes['a']) + str(nodes['b']))
# 添加到队列中
queue.append(nodes) # 加入到队列中
# 记录其父节点
nodes['parent'] = vertex # 这里可以优化
# parent.append(nodes)
# return graph, parent
return graph
## 操作类型
actions = ["FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"]
## 输入
VA,VB,VC = map(int,input().strip().split(' '))
print(VA,VB,VC )
graph = collections.defaultdict(list)
nodes = collections.defaultdict(list)
# parent = collections.defaultdict(list)
# vertex,parent = bfs(graph,VA,VB,VC)
vertex = bfs(graph,VA,VB,VC)
steps = vertex['step']
print(steps) # 涉及的总步数
Show_actions = []
Show_actions.append(vertex['flag'])
temp = vertex
for i in range(steps-1):
temp = temp['parent']
Show_actions.append(temp['flag'])
for i in range(steps-1,-1,-1):
print(actions[Show_actions[i]])
输入:
3 5 4输出:
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)
版权声明:本文为xxdragon126原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。