盆
描述
给你两个锅,体积分别为 A 升和 B 升。可以执行以下操作:
-
fill(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
-
drop(i) empty the pot i to the drain;
-
pour(i, j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).
意思就是到一次全部倒完,要么i空要么j空
编写一个程序来查找这些操作的最短可能序列,这些操作将在其中一个锅中产生恰好 C 升水。
输入
第一行也是唯一的一行是数字 A、B 和 C。这些都是从 1 到 100 和 C ≤ max(A,B) 范围内的整数。
输出
输出的第一行必须包含运算序列 K 的长度。以下 K 行必须分别描述一个操作。如果有多个最小长度的序列,则输出其中任何一个。如果无法实现所需的结果,则文件的第一行和唯一一行必须包含单词“不可能”。
示例输入
3 5 4
示例输出
6 FILL(2) POUR(2,1) DROP(1) POUR(2,1) FILL(2) POUR(2,1)
又是输出最小的值
那么就要用BFS(一般来说DFS是求总共的数目用)
因为有的操作都需要两个锅同时进行,也就是需要记录两个状态,因此定义一个结构体
class pots: def __init__(self, p1, p2, action): self.p1 = p1 self.p2 = p2 self.action = action
原来在这里用了index用于记录步数(说一下为什么想到用index来记录步数,因为可以新建一个step数组,需要给很大的初始长度,然后对应的进队列元素会有一个索引,用step[该索引] = step[上一个索引] + 1可以表示这里的步长)
better
那么这里为什么可以不用索引呢,因为有一种更好的办法,就是直接记录他的每一步操作,用一个action数组存储(但是需要deepcopy)因为直接将end.action = head.action会是浅复制,会出大问题。最后用了几步就是len(end.action)
BFS
def BFS(a, b, c):
import queue
q = queue.Queue()
node = pots(0, 0, [])
q.put(node)
indexes = [0]
while not q.empty():
head = q.get()
for i in range(6): # 6种状态,第一种是填满i,第二种填满j,依次类推
end = pots(head.p1, head.p2, [])
end.action = copy.deepcopy(head.action)
if i == 0:
if end.p1 == a:#p1为满的时候不能fill
continue
end.p1 = a
elif i == 1:
if end.p2 == b:#p2为满的时候不能fill
continue
end.p2 = b
elif i == 2: # 倒水
if end.p1 == 0:#p1为空不能倒水
continue
end.p1 = 0
elif i == 3:
if end.p2 == 0:#p2为空不能倒水
continue
end.p2 = 0
elif i == 4: # 第五种就是将i的水导入j中:有几种情况要舍去
if end.p1 == 0: # i中没有水不能倒
continue
if end.p2 == b: # j中是满的不能倒
continue
jleft = b - end.p2
if jleft >= end.p1:
end.p2 = end.p1 + end.p2
end.p1 = 0
else:
end.p1 = end.p1 - jleft
end.p2 = b
elif i == 5:
if end.p1 == a:
continue
if end.p2 == 0:
continue
ileft = a - end.p1
if ileft >= end.p2:
end.p1 = end.p1 + end.p2
end.p2 = 0
else:
end.p2 = end.p2 - ileft
end.p1 = a
end.action.append(i)
if end.p1 == c or end.p2 == c:
print(len(end.action))
for i in range(len(end.action)):
k = end.action[i]
if k == 0:
print("FILL(1)")
elif k == 1:
print("FILL(2)")
elif k == 2:
print("DROP(1)")
elif k == 3:
print("DROP(2)")
elif k == 4:
print("POUR(1,2)")
elif k == 5:
print("POUR(2,1)")
return
# print(i)
newnode = pots(end.p1, end.p2, end.action)
newnode.action = copy.deepcopy(end.action)
q.put(newnode)
这里对于index索引的变化需要格外注意,因为每次进入一个for,都只加了1到6的值
这样当下一层遍历的时候第一个加1就只是到了原来那个时候加2
因此我们创建一个indexes用于记录这个index有没有放过
indexes = [0, 50000] #只放两个初始的值
但是这样也会浪费很多时间,有什么好方法可以辨别不同的方案呢(除了index)
当然有,就是用action记录每次的步骤,记得用deepcopy
主体
if __name__ == '__main__': a, b, c = map(int, input().split()) BFS(a, b, c)
完整代码就在BFS中,就不展示了
文章描述了一个编程问题,要求通过两个容量分别为A和B的锅,使用fill,drop和pour操作,找到生成C升水的最短操作序列。解决方案是使用广度优先搜索(BFS),在每个状态下尝试所有可能的操作,并在找到目标状态时输出操作序列。代码中定义了状态类pots,用action数组记录每一步操作,通过BFS遍历状态空间,直到找到满足条件的序列。
491

被折叠的 条评论
为什么被折叠?



