📜  使用记忆的水壶问题

📅  最后修改于: 2021-09-22 10:29:48             🧑  作者: Mango

给定两个最大容量分别为mn升的水壶。水壶上没有标记,可以帮助我们测量较小的数量。任务是使用这两个水壶测量d升水。因此,我们的目标是从初始状态 (m, n) 到达最终状态 (0, d) 或 (d, 0)。

例子:

方法:使用 BFS 的方法已在上一篇文章中讨论过。在这篇文章中,讨论了一种使用记忆化和递归的方法。在任何时候,总共可以有六种可能性:

  • 完全清空第一个水壶
  • 完全清空第二个水壶
  • 装满第一个水壶
  • 装满第二个水壶
  • 将第二个水壶中的水倒入第一个水壶中,直到第一个水壶已满或第二个水壶没有水为止
  • 将第一个水壶中的水倒入第二个水壶中,直到第二个水壶已满或第一个水壶没有水为止

方法:使用递归,一一访问所有六种可能的移动,直到其中之一返回 True。由于可以重复相同的递归调用,因此每个返回值都使用记忆存储,以避免再次调用递归函数并返回存储的值。

下面是上述方法的实现:

# This function is used to initialize the 
# dictionary elements with a default value.
from collections import defaultdict
  
# jug1 and jug2 contain the value 
# for max capacity in respective jugs 
# and aim is the amount of water to be measured. 
jug1, jug2, aim = 4, 3, 2
  
# Initialize dictionary with 
# default value as false.
visited = defaultdict(lambda: False)
  
# Recursive function which prints the 
# intermediate steps to reach the final 
# solution and return boolean value 
# (True if solution is possible, otherwise False).
# amt1 and amt2 are the amount of water present 
# in both jugs at a certain point of time.
def waterJugSolver(amt1, amt2): 
  
    # Checks for our goal and 
    # returns true if achieved.
    if (amt1 == aim and amt2 == 0) or (amt2 == aim and amt1 == 0):
        print(amt1, amt2)
        return True
      
    # Checks if we have already visited the
    # combination or not. If not, then it proceeds further.
    if visited[(amt1, amt2)] == False:
        print(amt1, amt2)
      
        # Changes the boolean value of
        # the combination as it is visited. 
        visited[(amt1, amt2)] = True
      
        # Check for all the 6 possibilities and 
        # see if a solution is found in any one of them.
        return (waterJugSolver(0, amt2) or
                waterJugSolver(amt1, 0) or
                waterJugSolver(jug1, amt2) or
                waterJugSolver(amt1, jug2) or
                waterJugSolver(amt1 + min(amt2, (jug1-amt1)),
                amt2 - min(amt2, (jug1-amt1))) or
                waterJugSolver(amt1 - min(amt1, (jug2-amt2)),
                amt2 + min(amt1, (jug2-amt2))))
      
    # Return False if the combination is 
    # already visited to avoid repetition otherwise
    # recursion will enter an infinite loop.
    else:
        return False
  
print("Steps: ")
  
# Call the function and pass the
# initial amount of water present in both jugs.
waterJugSolver(0, 0)
输出:
Steps: 
0 0
4 0
4 3
0 3
3 0
3 3
4 2
0 2

时间复杂度:O(M * N)
辅助空间:O(M * N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程