题目描述

有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。

你允许:

  • 装满任意一个水壶;
  • 清空任意一个水壶;
  • 从一个水壶向另外一个水壶倒水,直到装满或者倒空;
输入: x = 3, y = 5, z = 4
输出: True

解题思路

纯数学解法比较难搞,这是一个比较经典的图的“广度优先搜索”问题。我的实现。

  • BFS:(从一个或若干个起始点开始,沿着边像水波一样逐层向外遍历,直到所有的点已被访问或者到达目标状态。推荐看题解!)

    这一类游戏相关的问题,用人脑去想,是很难穷尽所有的可能情况的。因此很多时候需要用到**「搜索算法」**。

    「搜索算法」一般情况下是在「树」或者「图」结构上的「深度优先遍历」或者「广度优先遍历」。因此,在脑子里,更建议动手在纸上画出问题抽象出来的「树」或者「图」的样子。(遍历所有可能就解出来了

    关于图片的说明:

    • 节点表示两个水壶的状态;
    • 边表示操作方法:分别为倒满A/B,倒空A/B,A倒入B,B倒入A 六种方法;
    • 这是一个有向图,因为有些状态并不能互相转移。比如 (1,1) 和 (1,0)。

    在「树」上的「深度优先遍历」就是「回溯算法」,在「图」上的「深度优先遍历」是「flood fill」 算法(附议)。深搜比较节约空间。这道题由于就是要找到一个符合题意的状态,我们用广搜就好了。这是因为广搜有个性质,一层一层像水波纹一样扩散,路径最短

    所谓「状态」,就是指当前的任务进行到哪个阶段了,可以用变量来表示,怎么定义状态有的时候需要一定技巧,这道题不难。这里分别定义两个水壶为 AB,定义有序整数对 (a, b) 表示当前 AB 两个水壶的水量,它就是一个状态。

    其它细节请直接题解和代码,清晰易懂!

  • 数学方法:(这部分直接看题解即可,较难理解,面试不会问数学解法)

    • 我们认为,每次操作只会让桶里的水总量增加 x,增加 y,减少 x,或者减少 y。(原因看题解)
    • 因此,我们可以认为每次操作只会给水的总量带来 x 或者 y 的变化量。所以我们的目标可以改写成:找到一对整数 a, b,使得ax + by = z。若这样的a, b存在,那么我们的目标就是可以达成的。
    • 而贝祖定理告诉我们,ax + by = z 有解当且仅当 zx, y 的最大公约数的倍数。因此我们只需要找到 x, y 的最大公约数并判断 z 是否是它的倍数即可。

参考代码

BFS

class Solution {pair<int, int> op(int type, const pair<int, int> &state, int x, int y) {// 边表示操作方法:分别为倒满A/B,倒空A/B,A倒入B,B倒入A 六种方法。switch(type) {case 0 : return make_pair(x, state.second);case 1 : return make_pair(state.first, y);case 2 : return make_pair(0, state.second);case 3 : return make_pair(state.first, 0);case 4 :{int move = min(state.first, y-state.second);return make_pair(state.first - move, state.second + move);}case 5 : {int move = min(x-state.first, state.second);return make_pair(state.first + move, state.second - move);}}return make_pair(0, 0);}// 自定义的hash函数struct HashPair {size_t operator()(const pair<int, int> &key) const noexcept{return size_t(key.first)*100000007 + key.second;}};public:bool canMeasureWater(int x, int y, int z) {// 特判if(z == 0) return true;if(x + y < z) return false;unordered_set<pair<int,int>, HashPair> mark;queue<pair<int,int> > q;q.push(make_pair(0, 0));while(q.empty() == false) {auto node = q.front();q.pop();// 找到了目标状态if(node.first + node.second == z || node.first == z || node.second == z) {return true;}// 因为一共有六种操作方法for(int i = 0; i < 6; i++) {auto next = op(i, node, x, y);// 因为状态有重复,因此是一个「有向」且「有环」的图,在遍历的时候,需要判断该结点设置是否访问过if(mark.find(next) != mark.end()) {continue;}mark.insert(next);q.push(next);}}return false;}};

数学方法

class Solution {public:bool canMeasureWater(int x, int y, int z) {// 特判if(z < 0 || x + y < z) return false;if(z == 0) return true;int g;if(x == 0 || y == 0)  // 除数不为0g = x + y;elseg = gcd(x, y);return (z % g) == 0;}int gcd(int a,int b) {  // 辗转相除法if(b == 0)return a;return gcd(b, a % b);}
};

[LeetCode] 365、水壶问题相关推荐

  1. Leetcode.365 水壶问题

    题目链接 Leetcode.365 水壶问题 mid 题目描述 有两个水壶,容量分别为 x和 y升.水的供应是无限的.确定是否有可能使用这两个壶准确得到 z升. 如果可以得到 z升水,最后请用以上水壶 ...

  2. LeetCode 365. 水壶问题

    365. 水壶问题 题目链接-365. 水壶问题 解题思路 裴蜀定理 裴蜀等式:若a,ba,ba,b是整数,且gcd(a,b)=dgcd(a,b)=dgcd(a,b)=d,那么对于任意的整数x,yx, ...

  3. LeetCode 365. 水壶问题(最大公约数)

    文章目录 1. 题目 2. 最大公约数 1. 题目 有两个容量分别为 x升 和 y升 的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的 ...

  4. LeetCode —— 365. 水壶问题(Python3)

    有两个容量分别为 x升 和 y升 的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升水. 你允许: 装满任意一 ...

  5. LeetCode 365水壶问题(python)

    题目描述: 有两个容量分别为 x升 和 y升 的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水. 你允许 ...

  6. 每日一题-leetcode 365. 水壶问题

    有两个水壶,容量分别为 jug1Capacity 和 jug2Capacity 升.水的供应是无限的.确定是否有可能使用这两个壶准确得到 targetCapacity 升. 如果可以得到 target ...

  7. Leetcode 365.水壶问题

    水壶问题 有两个容量分别为 x升和 y升的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水. 你允许: 装满 ...

  8. LeetCode——365.水壶问题【贝祖定理】

    题解 AC-Code using PII = pair<int, int>;class Solution {public:bool canMeasureWater(int x, int y ...

  9. leetcode:365. 水壶问题【肥鼠定理,栈模拟dfs】

    分析:数学 显然最后的z是a和b的线性组合 也就是ax + by = z也就是说z是(a,b)的倍数 那就直接用gcd就好了 加个特判 ac code class Solution:def canMe ...

  10. [LeetCode解题报告] 365. 水壶问题

    [LeetCode解题报告] 365. 水壶问题 一. 题目 1. 题目描述 2. 原题链接 二. 解题报告 1. 思路分析 2. 复杂度分析 3. 代码实现 三. 本题小结 一. 题目 1. 题目描 ...

最新文章

  1. 一文提升你对深度学习分布式训练的整体认知!
  2. linux cp使用注意事项
  3. 动态链接库DLL与静态链接库LIB
  4. 弹性均质圆环法计算过程_蚝油的加工工艺,蚝油总固形物(水分含量)计算公式,检测方法...
  5. 在python函数中参数分类的详细教程
  6. 常用电子接口大全,遇到不认识的,就翻出来对照辨认!
  7. rust风化速度_反驳《Golang、Rust的执行速度的对照,让人大吃一惊。》——不会别瞎说...
  8. Jeecg-Boot 2.1.2版本发布,基于SpringBoot的快速开发平台
  9. 华为云薅羊毛攻略来袭,走过路过不要错过
  10. MoneyRunner API汇总
  11. 解决permission denied错误
  12. 国产卫星高分四号(GF4)预处理(辐射定标)
  13. pid调节软件_三面大疆惨败,因为不懂PID的积分抗饱和
  14. spark 算子使用类变量_SparkCore的常用算子
  15. JAR 文件规范详解
  16. ecplise和lomboz和tomcat配置
  17. HTML5 canvas元素绘制花朵等
  18. 【读书笔记】统计学:从数据到结论 第七章
  19. 利用计算机属性将字符串逆序输出,字符串逆序的各种实现算法
  20. 数据分析--数据预处理

热门文章

  1. 随意描绘风格的界面工具Balsamiq Mockups
  2. linux解决文件上传失败的问题
  3. 笔记本电脑计算机里面怎么管理,Win7笔记本电脑如何分盘?
  4. LeetCode:342(Python)—— 4 的幂(简单)
  5. java.lang.IllegalAccessException: class xxx is not accessible from class android.app.Instrumentation
  6. Java MVC设计模式
  7. 谁来拯救他们-可爱的海豚
  8. 【Notion AI 功能试用】写作修改、润色、总结、翻译效果
  9. 一个外贸经理的分享:7个找客户的方法和思路
  10. python 生成pdf收据_Python 内置收据结构之九(字典)