📜  使用备忘录的水壶问题

📅  最后修改于: 2021-04-26 17:54:44             🧑  作者: 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)