一.题目描述
现在拥有两个杯子,容量分别为a和b,要求使用这两个杯子量出c容量的水,并输出两个杯子所做的操作。
详细题目如下:

二.思路概述
使用bfs的思路。两个水杯初始状态都是0,而每一次都可以做六种不同的操作,这些操作会导致两个水杯变成不同的状态,再将这些状态入队列,再次进入循环,直到两个水杯中有一个里面的水量为c。在上述过程中,可使用map数组来记录每一个状态的前状态,便于回溯。

三.各部分作用
1.结构体pour:
a,b分别对应着两个杯子里的水量,操作符重载是为了map函数,六个函数对应着六种状态。

struct pour
{int a;int b;//两个杯子里的水量 pour(){}pour(int x,int y){a=x;b=y;}//操作符重载 pour& operator=(pour& val){a=val.a;b=val.b; return *this;}bool operator!=(const pour &va) const {return a!= va.a|| b != va.b ;}bool operator<(const pour &va) const {return a == va.a ? b < va.b : a < va.a;}//六种操作对应的函数 pour fillA(){return pour(A,b);} pour fillB(){return pour(a,B);}pour emptyA(){return pour(0,b);}pour emptyB(){return pour(a,0);}pour AtoB(){pour c;c.a=max(a+b-B,0);c.b=min(a+b,B);return c;} pour BtoA(){pour c;c.a=min(a+b,A);c.b=max(a+b-A,0);return c;}
};

2.check函数
用来给每一次改变状态后水量入队列和记录前驱状态

void check(pour m,pour n)//用来记录前一个状态
{if(mps.find(m)  == mps.end()){sp.push(m);mps[m]=n; }
}

3.print部分
根据最后的状态进行回溯,并将这些状态入栈,然后用栈从初状态开始输出结果。

void print(pour t)//pp的a或者b==C
{   while(!(t.a==0&&t.b==0)){   xp.push(t) ;pour va=mps[t];t=va;}xp.push(t); while(xp.size()>1 ){pour m=xp.top() ;xp.pop();pour n=xp.top() ;determine(m,n);} xp.pop() ;}

四.注意的问题
1.由于此题可能会做不止一次输入和输出,所以map数组、栈、队列都要注意是否清空,栈和队列没有直接清空的函数,需要手动进行。
2.map函数使用起来很方便,解决了很多问题,但是map函数的使用规则可能不是那么友好,比如在check函数中一定要第一行,确认关键字没有出现过,才插入,不然就会报错。

if(mps.find(m)  == mps.end()){sp.push(m);mps[m]=n; }

3.在回溯这个过程中,我尝试过使用数组和栈来存储进入队列的状态,但是都失败了,这两种方法都不好掌握,结果惨烈,最后使用了map。

五.完整代码

#include<iostream>
#include<map>
#include<queue>
#include<stack>
using namespace std;int A,B,C;
int nu=0;struct pour
{int a;int b;//两个杯子里的水 pour(){}pour(int x,int y){a=x;b=y;}pour& operator=(pour& val){a=val.a;b=val.b;return *this;}bool operator!=(const pour &va) const {return a!= va.a|| b != va.b ;}bool operator<(const pour &va) const {return a == va.a ? b < va.b : a < va.a;}//六种操作对应的函数 pour fillA(){return pour(A,b);} pour fillB(){return pour(a,B);}pour emptyA(){return pour(0,b);}pour emptyB(){return pour(a,0);}pour AtoB(){pour c;c.a=max(a+b-B,0);c.b=min(a+b,B);return c;} pour BtoA(){pour c;c.a=min(a+b,A);c.b=max(a+b-A,0);return c;}
};queue<pour> sp;//队列存储每次状态
stack<pour> xp;//栈
map<pour,pour> mps;void check(pour m,pour n)//用来记录前一个状态
{if(mps.find(m)  == mps.end()){sp.push(m);mps[m]=n; }}
void determine(pour m,pour n)
{if(n.a==A&&n.b==m.b)cout<<"fill A"<<endl;else if(n.b==B&&n.a==m.a)cout<<"fill B"<<endl;else if(n.a==0&&n.b==m.b)cout<<"empty A"<<endl;else if(n.b==0&&n.a==m.a)cout<<"empty B"<<endl;else if((n.a==0&&n.b==m.a+m.b)||(n.b==B&&n.a==m.a+m.b-B))cout<<"pour A B"<<endl;else if((n.b==0&&n.a==m.a+m.b)||(n.a==A&&n.b==m.a+m.b-A))cout<<"pour B A"<<endl;
}void print(pour t)//pp的a或者b==C
{   while(!(t.a==0&&t.b==0)){   xp.push(t) ;pour va=mps[t];t=va;}xp.push(t); while(xp.size()>1 ){pour m=xp.top() ;xp.pop();pour n=xp.top() ;determine(m,n);} xp.pop() ;}
void bfs(pour t)
{//从0,0开始为初始状态mps[t]=t; sp.push(t);while (!sp.empty()) {       t = sp.front();sp.pop();if (t.a == C ||t.b == C) //跳出循环,输出步骤 {//cout<<111<<endl;print(t);while(!sp.empty() )sp.pop() ;return;}//每次做完六种操作的状态进队列,直到x和y的值有一个为c停止check(t.AtoB(), t);check(t.BtoA(), t);check(t.fillA(), t);check(t.fillB(), t);check(t.emptyA(), t);check(t.emptyB(), t);//cout<<nu<<endl;      }//记录每次状态的前一个操作,最后输出所有的操作}
int main()
{while(cin>>A){cin>>B>>C;pour p(0,0);//初始状态, bfs(p);cout<<"success"<<endl;mps.clear() ;}return 0;
}

倒水问题(两个杯子)相关推荐

  1. 茶杯:N个杯子排成一排,第X个杯子藏有球,交换任意两个杯子K次后,找出藏球杯子位置。

    N个杯子排成一排,第X个杯子藏有球,交换任意两个杯子K次后,找出藏球杯子位置. (本文获得CSDN质量评分[92]) [学习的细节是欢悦的历程] Python 官网:https://www.pytho ...

  2. 用容积为15升和27升的两个杯子向一个水桶中注水,可以精确向一个水桶中注入多少升水呢

    用容积为15升和27升的两个杯子向一个水桶中注水,可以精确向一个水桶中注入多少升水呢? 选项有A.53 B.25 C.33 D.52 设杯子X容量15升,杯子Y容量27升. 若将杯子Y装满水,再倒入X ...

  3. 两个水壶相互倒水—水壶问题

    点击此处快速跳到程序部分 水壶问题 有两个容量分别为 x升 和 y升 的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取 ...

  4. 非常可乐(三个杯子倒水问题)

    题目描述 红红是个肥宅,所以他很爱喝肥宅快乐水.但是每次当红红买了肥宅快乐水后,左左都要求和红红一起分享这一瓶可乐,而且要和红红喝得一样多.但是红红手中只有两个杯子,他们的容量的分别是 N 毫升 和 ...

  5. 杯子倒水问题 -python

    题目:假设有两个杯子A ,B,用户只需要输入两个杯子的容量值和需要获取的杯子数值left_c.问两个杯子通过何种操作能获取到left_c 的数值. 分析:此题目是求解优化的问题.采用bfs算法. cl ...

  6. 倒水问题(Java)

    有两个杯子,一个杯子容量为3,另一个容量为5.  怎么倒水才能得到体积为4的水. 可以给一个杯子加满水.或倒光.或把一个杯子的水加到另一个杯子中. 1 import java.util.ArrayLi ...

  7. 杯子 + Kronican

    杯子 Kronican [题目描述] 重庆八中在80周年校庆的时候获捐n个杯子, 每个杯子有两个属性:一个是已装水量 ai,一个是可装水量 bi(ai <= bi). 从一个杯子向另一个杯子倒 ...

  8. Pots (模拟倒水)

    You are given two pots, having the volume of A and B liters respectively. The following operations c ...

  9. python两数交换 函数_Python 为什么只需一条语句“a,b=b,a”,就能直接交换两个变量?...

    从接触 Python 时起,我就觉得 Python 的元组解包(unpacking)挺有意思,非常简洁好用. 最显而易见的例子就是多重赋值,即在一条语句中同时给多个变量赋值: >>> ...

最新文章

  1. let 与 expr Shell运算比较 let强强胜出
  2. [architecture]-ARMV8的一些总结-一篇就够了
  3. CodeForces Round #291 Div.2
  4. Apollo进阶课程㊲丨Apollo自动驾驶架构介绍
  5. CSS 的导入方式 (link or import ?)
  6. shell学习之常用bash内置变量
  7. 蓝桥杯2015年第六届C/C++省赛C组第九题-打印大X
  8. CF989C A Mist of Florescence
  9. 深度学习之RNN循环神经网络(理论+图解+Python代码部分)
  10. Zoho中国:如何利用好免费版CRM
  11. lol人物模型提取(八)
  12. Python淘宝商品比价定向爬虫
  13. 软件授权文件.lic文件
  14. mysql的基础查阅
  15. System.Windows.Freezable 在未被引用的程序集中定义
  16. Tuscany的一些概念
  17. 2021年芒种是几月几号?芒种习俗有哪些 ?
  18. 反思一下自己工作中的几个问题
  19. 2021深圳实习日记
  20. 关于The requested URL returned error: 403

热门文章

  1. 基于深度学习的医学图像分割学习笔记(九)UNet 3+
  2. BFGS算法(Broyden-Fletcher-Goldfarb-Shanno算法)
  3. 维基百科创建需要注意哪些问题?
  4. 全国计算机java语言程序设计_2018年全国计算机等级考试二级教程:Java语言程序设计(2018年版)...
  5. Pycharm 小技巧-- filewacher+black自动格式化
  6. C++ Primer 第5版--练习9.14
  7. Hangfire 基本使用
  8. idea的去除转义的复制粘贴
  9. 平衡小车c语言程序,【全部开源】两轮平衡小车(原理图、PCB、程序源码、BOM等)...
  10. 利用Python做excel文本合并(根据左侧单元格,快速合并右侧单元格内容)