问题:有一个充满水的8品脱的水壶和两个空水壶(容积分别是5品脱和3品脱)。通过将水壶完全倒满水和将水壶的水完全倒空这两种方式,在其中的一个水壶中得到4品脱的水。

解法:可以把每次三个水壶中水的量组成一个状态,比如初始状态为008,对应第一个水壶0品脱水,第二个水壶0品脱水,第三个水壶8品脱水。对题目的状态空间图进行广度优先遍历。当表示状态的数字中出现4时,即求出答案。

1、为了打印出倒水的过程,需要声明一个前置状态保存当前状态由哪个状态转换而来,然后就可以回溯到初始状态,打印出倒水过程。相当于树中的父结点。

2、可以声明一个map表,保存已有的状态,对已有的状态,就不再向下继续遍历,这样可以节省求解时间。

3、因为是广度优先遍历,所以第一次解得的答案所需的倒水的次数最少,解为最优解。

#include <iostream>
#include <vector>
#include <map>
#define MaxFirst 3
#define MaxSecond 5
#define MaxThird 8
using namespace std;class State
{
public:int second;int num[3];State* preState;static map<int,int> mapping;public:State(int first,int second,int third){num[0]=first;num[1]=second;num[2]=third; }void init(){       mapping[0]=MaxFirst;mapping[1]=MaxSecond;mapping[2]=MaxThird;}bool canPour(int from,int to)//判断是否可以从from水壶中倒水到to水壶中{if(num[from]==0){return false;}if(num[to]==mapping[to]){return false;}else {return true;}}void pour(int from,int to)//倒水过程{if(num[from]+num[to]>mapping[to]){num[from]=num[from]-(mapping[to]-num[to]);num[to]=mapping[to];}else{num[to]=num[to]+num[from];num[from]=0;}}};
map<int,int> State::mapping;int main()
{map<int,int> states;State *start=new State(0,0,8);start->init();State *state=start;State *endState=new State(8,8,8);//只有获得解endState才会改变,赋值全为8为了方便判断是否获得最终解vector<State> action;//保存所有状态对象action.push_back(*start);//把初始状态先加入队列中int n=0;do{for(int i=0;i<3;i++)//双层循环为从i水壶中倒水入j水壶中{for(int j=0;j<3;j++){if(i!=j){if(state->canPour(i,j)){state->pour(i,j);if(states[state->num[0]*100+state->num[1]*10+state->num[2]]==0)//如果该状态不在hash表中,即为第一次出现该状态{states[state->num[0]*100+state->num[1]*10+state->num[2]]++;(state->preState)=new State(action[n]);action.push_back(*state);if(state->num[0]==4||state->num[1]==4||state->num[2]==4)//获得解{endState=state;i=4;break;   }}}}*state=action[n];}         }n++;}while(endState->num[0]==8&&endState->num[1]==8&& n<action.size());cout<<endState->num[0]<<" "<<endState->num[1]<<" "<<endState->num[2]<<endl;state=endState;do{state=state->preState;cout<<state->num[0]<<" "<<state->num[1]<<" "<<state->num[2]<<endl;     }while(state->num[2]!=8);return 0;
}

运行结果如图,从下往上即为倒水的过程

如果需要倒出水壶含7品脱的情况,把

if(state->num[0]==4||state->num[1]==4||state->num[2]==4)

中的4改成7,运行出结果如下:

算法谜题——三个水壶问题相关推荐

  1. 《算法谜题》-第二章 谜题

    1.狼羊菜过河 2.手套选择 3.矩形切割 4.士兵摆渡 5.行列变换 6.数数的手指 7.夜过吊桥 8.拼图问题 9.心算求和 10.硬币中的假币 11.假币堆问题 12.平铺多米诺问题 13.被堵 ...

  2. c语言勾股定理程序流程图,方法总结1.表达算法的方法有自然语言.流程图和基本算法语句三种.先有自然语言.再画流程图.最后才能写出基本算法语句.即程序,——青夏教育精英家教网——...

    考点一:自然语言表示的算法 [内容解读]通过对解决具体问题过程与步骤的分析,体会算法的思想,了解算法的含义:对于某一问题往往可以设计出多种算法,通过选用步骤最少的.结构最好的算法. [命题规律]以选择 ...

  3. K-means聚类算法的三种改进(K-means++,ISODATA,Kernel K-means)介绍与对比

    原文:http://www.cnblogs.com/yixuan-xu/p/6272208.html K-means聚类算法的三种改进(K-means++,ISODATA,Kernel K-means ...

  4. 用python解算法谜题_编程的乐趣 用Python解算法谜题

    这是一本介绍通过解决复杂谜题来学习编程的书,书中的代码用Python语言编写.与以往的编程书不同,本书将对代码功能的理解与编程语言语法和语义的理解分离开来,从解每个谜题开始,先给出解谜题的算法,随后用 ...

  5. leetcode旋转数组 c语言,leetcode explore 初级算法第三题,旋转数组代码实现

    leetcode explore 初级算法第三题,旋转数组代码实现.原题链接: 题目分析 因为题目不是很长,这里把题目贴出来: 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. ...

  6. 理解GBDT算法(三)——基于梯度的版本

     理解GBDT算法(三)--基于梯度的版本 标签: GBDT梯度残差代价函数回归树 2015-03-31 16:13 1395人阅读 评论(3) 收藏 举报 本文章已收录于: 分类: Machin ...

  7. 有向图最长路径算法_算法数据结构 | 三个步骤完成强连通分量分解的Kosaraju算法...

    强连通分量分解的Kosaraju算法 今天是算法数据结构专题的第35篇文章,我们来聊聊图论当中的强连通分量分解的Tarjan算法. Kosaraju算法一看这个名字很奇怪就可以猜到它也是一个根据人名起 ...

  8. js实现阶乘算法的三种方法

    js实现阶乘算法的三种方法 // 非递归写法 function f(n) {if (0 === n) {return 1;}let res = 1;for (let i = 1; i <= n; ...

  9. A*算法(三)算法实现

    A*算法(三)算法实现 1. Array2D类 2. Point类 3. AStar类 3.1 Node类 3.2 初始化处理 3.3 判断函数 3.4 搜索结点周围的点 3.5 寻路 4. 地图显示 ...

最新文章

  1. 工作中常用的第三放的框架
  2. Centos7安装Python3并更改默认版本为python3(编译安装)
  3. 如何用计算机打出love,游戏中名字的LOVE怎么用符号打出来?
  4. MyBatis开发步骤
  5. CODEVS——T 1049 棋盘染色
  6. HTML 文档流和文本流的理解
  7. git eclipse 取消误操作 ignore(忽略)文件
  8. c语言if语句判断ab大小,C语言条件语句ifppt课件
  9. Spring Boot 项目集成Windows域账户认证
  10. MFC调用RDP实现远程桌面共享实例
  11. 平面图最小割 BZOJ 2006
  12. S4 HANA CO和FI自动集成:成本中心分配分摊业务实践-KSV5/KSU5
  13. 【翻译】WhatsApp 加密概述(技术白皮书)
  14. 新媒体运营 | 6个自动写文案的宝藏网站,助你摆脱灵感枯竭
  15. office2007的Excel当中如何打开两个独立窗口
  16. 【算法Algorithm】计数(Count)排序
  17. cocos creator中FBX文件不可用显示asset invalid
  18. Flink 计算 TopN
  19. 基础SQL Server 操作问题——仅当使用了列表并且IDENTITY_INSERT为ON时,才能为表中的标识列制定显示值
  20. COINDAO将迎来首次回购分红,COINDAO白名单和团队长参与方式。

热门文章

  1. 计划任务备份MSSQL_se7en3_新浪博客
  2. 日期加减天数计算,时间戳日期相互转换
  3. 德鲁克日志读后感之八十八
  4. Spring 马士兵
  5. excel的vlookup常用查找功能
  6. 程序化那么神秘,究竟在做什么事情
  7. “梅西”式核心员工,正在摧毁你的团队
  8. 电脑鼠标如何进行维护
  9. 「AI初识境」给深度学习新手做项目的10个建议
  10. ubuntu14.04+cuda6.5+opencv2.4.9+cuda-convnet2配置