每日一题:365. 水壶问题(待改进)

365. 水壶问题
有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?
如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。
你允许:
装满任意一个水壶
清空任意一个水壶
从一个水壶向另外一个水壶倒水,直到装满或者倒空
示例 1: (From the famous “Die Hard” example)
输入: x = 3, y = 5, z = 4
输出: True
示例 2:
输入: x = 2, y = 6, z = 5
输出: False

解题思路一:
分析一下
不可能有两个壶同时处于不满不空的状态
装满只对空瓶操作,否则相当于之前操作作废
倒水不改变水的总量
装满操作是加法
清空操作是减法
二者都以操作对象容量为运算对象
操作次数相当于系数
运算结果为mx+ny
验证一下对系数基本没有要求,运算结果只要在允许范围内都可以得到
代码实现
mx+ny的取值是最大公因数的倍数
只要验证z是不是最大公因数的倍数就好了
代码如下:

class Solution {
public:
    bool canMeasureWater(int x, int y, int z) {
        if(z<0||z>x+y)
        return false;
        if(z==0) return true;//边界
        int g;
        if(x==0||y==0)//除数不为0
            g=x+y;
        else
            g=gcd(x,y);
        return z%g==0;
    }
    int gcd(int a,int b)//辗转相除法,找出最大公约数
    {
        if(a%b==0)
            return b;
        return gcd(b,a%b);
    }

};

思路二:利用深度优先搜索

class Solution {
public:
    bool canMeasureWater(int x, int y, int z) {
        int a[2];
        a[0]=x;a[1]=y;
        bool ans=true;
        dfs(a,x,y,z,ans);
        return ans;
    }
    void dfs(int a[],int x,int y,int z,bool &ans){
        if(sizeof(a)==2){
        int a1=a[0],a2=a[1];
        if(a1==z || a2==z || a1+a2==z){
            ans=true;
            return;
        }
        a[0]=0;
        a[1]=a2;
        dfs(a,x,y,z,ans);//将x倒完
        a[0]=a1;
        a[1]=0;
        dfs(a,x,y,z,ans);//将y倒完
        a[0]=x;
        a[1]=a2;
        dfs(a,x,y,z,ans);//将x灌满
        a[0]=a1;
        a[1]=y;
        dfs(a,x,y,z,ans);//将y灌满
        a[0]=max(a1-(y-a2),0);
        a[1]=min(a2+a1,y);
        dfs(a,x,y,z,ans);//从x向y倒
        a[0]=min(a2+a1,x);
        a[1]=max(a2-(x-a1),0);
        dfs(a,x,y,z,ans);//从y向x倒
    }
    }
};//会陷入无限循环,需要改进目前无方案解决
发布了70 篇原创文章 · 获赞 39 · 访问量 2264

猜你喜欢

转载自blog.csdn.net/weixin_45221477/article/details/105018609