[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
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.
這是一道腦筋急轉彎題,我想很多人以前應該聽過這道題目,有一個容量為3升和一個容量為5升的水罐,問我們如何準確的稱出4升的水。我想很多人都知道怎麼做,先把5升水罐裝滿水,倒到3升水罐裡,這時5升水罐裡還有2升水,然後把3升水罐裡的水都倒掉,把5升水罐中的2升水倒入3升水罐中,這時候把5升水罐解滿,然後往此時有2升水的3升水罐裡倒水,這樣5升水罐倒出1升後還剩4升即為所求。這個很多人都知道,但是這道題隨意給我們了三個引數,問有沒有解法,這就比較難了。這裡我就照搬
這道問題其實可以轉換為有一個很大的容器,我們有兩個杯子,容量分別為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不可能稱出比它們之和還多的水,參見程式碼如下;
class Solution { public: bool canMeasureWater(int x, int y, int z) { return z == 0 || (x + y >= z && z % gcd(x, y) == 0); } int gcd(int x, int y) { return y == 0 ? x : gcd(y, x % y); } };
參考資料: