1. 程式人生 > >[LeetCode] Water and Jug Problem 水罐問題

[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.

這是一道腦筋急轉彎題,我想很多人以前應該聽過這道題目,有一個容量為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);
    }
};

參考資料: