【leetcode】【medium】【每日一题】365. Water and Jug Problem​​​​​​​

230 篇文章 0 订阅

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

题目链接:https://leetcode-cn.com/problems/water-and-jug-problem/

 

思路

法一:dfs递归

对于本题来说,这种方法非常耗时。但如果题目要求给出倒水步骤的具体解,数学方法就不行,需要用递归的方法。

!以下代码中关于set存储pair的内容是用的别人代码,目前只能照着背。

class Solution {
    // 0-x装满,1-y装满,2-x倒光,3-y倒光,4-x全给y,5-y给x满上
public:
    bool canMeasureWater(int x, int y, int z) {
        if(z==0||z==x||z==y||z==x+y) return true;
        if(z>x+y || z<0) return false;
        if(x==0) return z==y;
        if(y==0) return z==x;
        auto hash_function = [](const pair<int,int>& o) {return hash<int>()(o.first) ^ hash<int>()(o.second);};
        unordered_set<pair<int,int>, decltype(hash_function)> dp(0, hash_function);
        stack<pair<int,int>> stk;
        pair<int, int> cur = make_pair(0,0);
        stk.push(cur);
        while(!stk.empty()){
            cur = stk.top();
            stk.pop();
            if(dp.count(cur)) continue;
            dp.insert(cur);
            int num1 = cur.first, num2 = cur.second;
            if(x+num2==z || num1+y==z ||num1==z ||num2==z ||num1+num2==z) return true;
            stk.emplace(x,num2);
            stk.emplace(num1,y);
            stk.emplace(0,num2);
            stk.emplace(num1,0);
            int num4y = min(y,num2+num1), num4x = max(num1+num2-y,0);
            stk.emplace(num4x,num4y);
            int num5x = min(x, num1+num2), num5y = max(0,num2-x+num1);
            stk.emplace(num5x,num5y);
        }
        return false;
    }
};

法二:数学规律

贝祖定理,z=ax+by 有解当且仅当 z 是 x,y 的最大公约数的倍数。因此我们只需要找到 x,y 的最大公约数并判断 z是否是它的倍数即可。

最大公因数可由辗转相除法计算得到。

class Solution {
public:
    bool canMeasureWater(int x, int y, int z) {
        if(z==0||z==x||z==y||z==x+y) return true;
        if(z>x+y || z<0) return false;
        if(x==0) return z==y;
        if(y==0) return z==x;
        int g = gcd(x,y);
        return z%g==0;
    }
    int gcd(int a, int b){
        if(a%b==0) return b;
        else return gcd(b,a%b);
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值