水壶问题

简单版本

这个问题算是水壶问题的简单版本,也是小时候竞赛中遇到过的,当时一直不知道怎么解。
偶然看到这么一个问题。其问题是,给定一个8升的满的水壶,一个5升的,一个3升的空水壶。问如何倒水可以倒出一个4升的水壶。每次只能将一个水壶倒满或者倒空。

以前一直不知道,原来这道题的核心思想就是bfs的状态表示。思路如下:

  1. 将8升往5升倒。
  2. 将8升往3升倒。
  3. 将5升往8升倒。
  4. 将5升往3升倒。
  5. 将3升依次类推。

然后用一个Data的struct来表示状态。同时,要注意记录每次出现的状态,当出现重复的状态就去剪枝叶。

代码

//c++ program
//design by >^.^<
//@date    2019-08-27 10:49:45
#include <iostream>
#include <queue>
#include <set>
#include <stdio.h>
// 这里是一个水壶问题的简化版本
// 就是给定三个水壶,分别是8,5,3升,8是满的,5,3是空的,
// 问如何让一个水壶装满4升。struct Data{int a;int b;int c;void output(){printf("(%d, %d, %d)", a, b, c);}bool operator<(const Data& rhs)const{if(a == rhs.a){if(b == rhs.b){return c < rhs.c;}else{return b < rhs.b;}}else{return a < rhs.a;}}
};
// 思路:用bfs的方法using namespace std;
int main()
{const int capA = 8;const int capB = 5;const int capC = 3;queue<Data> myQueue;myQueue.push(Data{8, 0, 0});set<Data> visited;visited.insert(Data{8, 0, 0});int x = visited.size();while(!myQueue.empty()){// 获得当前状态auto tmp = myQueue.front();myQueue.pop();if(tmp.a == 4 || tmp.b == 4){tmp.output();cout << endl;return 0;}// 计算下一个状态int topour = 0;set<Data> tmpSet;// a倒水给b// a只能倒这么多水topour = min(tmp.a, capB - tmp.b);auto dataA2B = Data{tmp.a-topour, tmp.b+topour, tmp.c};tmpSet.insert(dataA2B);// a倒水给ctopour = min(tmp.a, capC - tmp.c);auto dataA2C = Data{tmp.a-topour, tmp.b, tmp.c+topour};tmpSet.insert(dataA2C);// b倒水给atopour = min(tmp.b, capA - tmp.a);auto dataB2A = Data{tmp.a+topour, tmp.b-topour, tmp.c};tmpSet.insert(dataB2A);// b倒水给ctopour = min(tmp.b, capC - tmp.c);auto dataB2C = Data{tmp.a, tmp.b-topour, tmp.c+topour};tmpSet.insert(dataB2C);// c倒水给atopour = min(tmp.c, capA - tmp.a);auto dataC2A = Data{tmp.a+topour, tmp.b, tmp.c-topour};tmpSet.insert(dataC2A);// c倒水给btopour = min(tmp.c, capB - tmp.b);auto dataC2B = Data{tmp.a, tmp.b+topour, tmp.c-topour};tmpSet.insert(dataC2B);int m = tmpSet.size();for(auto eachStatus : tmpSet){if(visited.count(eachStatus) != 0){continue;}else{eachStatus.output();visited.insert(eachStatus);myQueue.push(eachStatus);}}cout << endl;}}

正常版本

有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?

如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。

你允许:

装满任意一个水壶
清空任意一个水壶
从一个水壶向另外一个水壶倒水,直到装满或者倒空
示例 1: (From the famous “Die Hard” example)

输入: x = 3, y = 5, z = 4
输出: True

思路

这里的思路其实和上面非常相似。只不过这里多了个无限大的水壶。所以多了几种状态。

  1. 把x水倒空。
  2. 把x水倒满。
  3. 把x水倒到y里面。
  4. 同理对y。

我认为这个思路要比leetcode题解上面那个要重要很多。而且算是让我对bfs有了一个很深刻的理解。

代码

class Solution {public:struct Data{int x;int y;bool operator<(const Data&rhs) const{if(x == rhs.x){return y < rhs.y;}else{return x < rhs.x;}}};bool canMeasureWater(int x, int y, int z) {if(x + y < z)return false;const int capX = x;const int capY = y;Data root{0, 0};queue<Data> myQueue;set<Data> visited;myQueue.push(root);visited.insert(root);while(!myQueue.empty()){auto temp = myQueue.front();myQueue.pop(); if(temp.x + temp.y == z)return true;// 获取下一个状态set<Data> tempSet;// x倒满tempSet.insert(Data{capX, temp.y});// y倒满tempSet.insert(Data{temp.x, capY});// x倒空tempSet.insert(Data{0, temp.y});// y倒空tempSet.insert(Data{temp.x, 0});// x倒水给yint x2y = min(temp.x, capY - temp.y);    tempSet.insert(Data{temp.x - x2y, temp.y + x2y});// y倒水给xint y2x = min(temp.y, capX - temp.x);tempSet.insert(Data{temp.x + y2x, temp.y - y2x});for(auto eachStatus : tempSet){// 如果这个状态已经存在,就剪枝if(visited.count(eachStatus) != 0){continue;}else{visited.insert(eachStatus);myQueue.push(eachStatus);}}}return false;}
};

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. 行波和驻波动画演示gif_新技能get√ | 语文课上的笔顺动画可以这么做
  2. oracle 增长型分区,oracle 11g 分区表创建(自动按年分区)
  3. 2019手卫生定义_2021年卫生资格考试部分科目大纲和教材变化归总!
  4. Teiid:数据虚拟化Data Virtualization平台
  5. KeyMob:为国内应用开发者管理的广告聚合平台
  6. TensorFlow(2)-训练数据载入
  7. Git前世今生-版本控制软件的发展
  8. Java多线程-线程的生命周期
  9. 项目管理的49个过程整理
  10. excel拆分单元格内容_Excel中最神奇的一个快捷键!牛!!
  11. 低光照图像增强论文Low-Light Image Enhancement with Normalizing Flow阅读笔记
  12. tf.trian.match_filenames_once
  13. ansys apdl变量基本操作
  14. 证书类型、自签CA证书、https双向认证(一篇就懂系列)
  15. 顶尖量化交易公司 CEO 如何缔造量化金融王国?
  16. 小篮子玩意儿、你苏爷就是扣字神话不服气么。
  17. Nolia 给CC添加过滤器
  18. Android 文件打开方式
  19. #创新应用#全球快递追踪:五次查询只需1KB!
  20. stlinkv2红灯闪烁_STLINK V2安装使用详解

热门文章

  1. 清除数组内容函数memset函数
  2. 8 项 Python 基本技能
  3. mysql between和in_mysql between and、==、in性能实例分析
  4. html4可以class,class4:HTML入门.ppt
  5. The user specified as a definer (‘root‘@‘%‘) does not exist
  6. 人遛狗程序,狗在特定的时间做指定的事情
  7. Cerveau Technologies, Inc.与日本东京都老人综合研究所签订研究协议
  8. 什么是 SUSE Studio?
  9. 10月26日绿健简报,星期三,农历十月初二
  10. 集合 ListT 排重方法 Distinct()