[LeetCode] Water and Jug Problem 水罐问题

You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. You need to determine whether it is possible to measure exactly z litres using these two jugs.

If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end.

Operations allowed:

  • Fill any of the jugs completely with water.
  • Empty any of the jugs.
  • Pour water from one jug into another till the other jug is completely full or the first jug itself is empty.

Example 1: (From the famous "Die Hard" example)

Input: x = 3, y = 5, z = 4
Output: True

Example 2:

Input: x = 2, y = 6, z = 5
Output: False

Credits:
Special thanks to @vinod23 for adding this problem and creating all test cases.

这道问题其实可以转换为有一个很大的容器,我们有两个杯子,容量分别为x和y,问我们通过用两个杯子往里倒水,和往出舀水,问能不能使容器中的水刚好为z升。那么我们可以用一个公式来表达:

z = m * x + n * y

其中m,n为舀水和倒水的次数,正数表示往里舀水,负数表示往外倒水,那么题目中的例子可以写成: 4 = (-2) * 3 + 2 * 5,即3升的水罐往外倒了两次水,5升水罐往里舀了两次水。那么问题就变成了对于任意给定的x,y,z,存不存在m和n使得上面的等式成立。根据裴蜀定理,ax + by = d的解为 d = gcd(x, y),那么我们只要只要z % d == 0,上面的等式就有解,所以问题就迎刃而解了,我们只要看z是不是x和y的最大公约数的倍数就行了,别忘了还有个限制条件x + y >= z,因为x和y不可能称出比它们之和还多的水,参见代码如下;

 1 class Solution(object):
 2     def canMeasureWater(self, x, y, z):
 3         dmax = max(x, y)
 4         dmin = min(x, y)
 5         if dmin ==0 and dmax ==z or z ==0:
 6             return True
 7         elif dmin == 0 and dmax != z or x+y<z:
 8             return False
 9         resid = self.gcd(dmax, dmin)
10         return True if z % resid == 0 else False
11 
12     def gcd(self, x, y):
13         return x if y == 0  else self.gcd(y, x%y)
14 
15 x = 11
16 y = 13
17 z = 2
18 s = Solution()
19 print s.canMeasureWater(x,y,z)
原文地址:https://www.cnblogs.com/lovely7/p/5852209.html