算法系列(二) 三只水桶等分水问题

有一个容积为8升的水桶里装满了水,另外还有一个容积为3升的空桶和一个容积为5升的空桶,如 何利用这两个空桶等分8升水?附加条件是三个水桶都没有体积刻度,也不能使用其它辅助容器。

这是一道经典题目,一般人都可以在一分钟内给出答案,不过,很多人可能没有注意到这道题 的答案不是唯一的。先来看看最常见的一个答案,也是目前已知最快的操作步骤,共需要7次倒水动作 :

从容积是8升的桶中倒5升水到容积是5升的桶中

从容积是5升的桶中倒3升水到容积是 3升的桶中

从容积是3升的桶中倒3升水到容积是8升的桶中

从容积是5升的桶中倒2升水 到容积是3升的桶中

从容积是8升的桶中倒5升水到容积是5升的桶中

从容积是5升的桶中 倒1升水到容积是3升的桶中

从容积是5升的桶中倒3升水到容积是8升的桶中

<结束 >

这里再给出一个稍微复杂一点的答案,这个答案需要8次倒水动作:

从容积是8升 的桶中倒3升水到容积是3升的桶中

从容积是3升的桶中倒3升水到容积是5升的桶中

从容 积是8升的桶中倒3升水到容积是3升的桶中

从容积是3升的桶中倒2升水到容积是5升的桶中

从容积是5升的桶中倒5升水到容积是8升的桶中

从容积是3升的桶中倒1升水到容积是5 升的桶中

从容积是8升的桶中倒3升水到容积是3升的桶中

从容积是3升的桶中倒3升水到 容积是5升的桶中

<结束>

到底有多少种答案呢?这里先卖个关子,耐心看完本文 你就知道了。

解决问题的思路

如果用人的思维方式,那么解决这个问题的关键是怎么通过倒水凑出确定的1升水或能容纳1升水的 空间,考察三只水桶的容积分别是3、5和8,用这三个数做加减运算,可以得到很多组答案,例如:

3 – (5 - 3) = 1

这个策略对应了上面提到的第一种解决方法,而另一组运算:

(3 + 3)- 5 = 1

则对应了上面提到的第二种解决方法。

但是计算机并不能理 解这个“1”的重要性,很难按照人类的思维方式按部就班地推导答案,因此用计算机解决这个问题, 通常会选择使用“穷举法”。为什么使用穷举法?因为这不是一个典型意义上的求解最优解的问题, 虽然可以暗含一个求解倒水次数最少的方法的要求,但就本质而言,常用的求解最优解问题的高效的 方法都不适用于此问题。如果能够穷举解空间的全部合法解,然后通过比较找到最优解也是一种求解 最优解的方法。不过就本题题意而言,并不关心什么方法最快,能求出全部等分水的方法可能更符合 题意。

如果我们把某一时刻三个水桶中存水的容积称为一个状态,则问题的初始状态是8升的 水桶装满水,求解的解出状态(最终状态)是8升水桶中4升水,5升水桶中4升水。穷举法的实质就是 把从初始状态开始,根据某种状态变化的规则搜索全部可能的状态,每当找到一个从初始状态到最终 状态的变化路径,就可以理解为找到了一种答案。这样的状态变化搜索的结果通常是得到一棵状态搜 索树,根节点是初始状态,叶子节点可能是最终状态,也可能是某个无法转换到最终状态的中间状态 ,状态树有多少个最终状态的叶子节点,就有多少种答案。根据以上分析结果,解决本问题的算法关 键有三点:首先,建立算法的状态模型;其次,确定状态树的搜索算法(暗含状态转换的规则);最 后,需要一些提高算法效率的手段,比如应用“剪枝”条件避免重复的状态搜索,还要避免状态的循 环生成导致搜索算法在若干个状态之间无限循环。

时间: 2024-11-01 11:29:16

算法系列(二) 三只水桶等分水问题的相关文章

算法系列(三) 妖怪与和尚过河问题

有三个和尚(或传教士)和三个妖怪(或食人怪)过河,只有一条能装下两个人(和尚或妖怪)的 船,在河的任何一方或者船上,如果妖怪的人数大于和尚的人数,那么和尚就会有被吃掉的危险.你 能不能找出一种安全的渡河方法呢? 这是一个很有意思的智力题,但是并不难,每次可以选择 一个人或者两个人过河,只要保证在河的任何一边的和尚数量总是大于或等于妖怪的数量即可.这里 先给出一种过河方法: 两个妖怪先过河,一个妖怪回来: 再两个妖怪过河,一个妖怪 回来: 两个和尚过河,一个妖怪和一个和尚回来: 两个和尚过河,一个

算法系列(二)

长时间没接着写了,今天接着未完成的革命,接下来就是快速排序: 快速排序的思想就是先选取一个基准点,然后将小于基准点的放在基准点的左边,大于基准点的数放在基准点右边,然后将左.右边的数组再重复上述步骤直到全部排序完成. 还是如数组:20 .40.50.10.60      left指针指向20,right指针指向60,base参照数指向20. 其实思想是蛮简单的,就是通过第一遍的遍历(让left和right指针重合)来找到数组的切割点. 第一步:首先我们从数组的left位置取出该数(20)作为基准

算法系列(三)

那么接下来就是选择排序: 选择排序就是先选数组中最大的一个,再选剩下中的最大一个,如此反复直到最后一个,其思想就是平时我们的一般正常的排序思想. 接下来用JS代码来实现: 1 //选择排序 2 function SelectionSort(arr){ 3 for(var i=0;i<arr.length-1;i++){ //要循环的次数 4 var temp=i;//默认的最小数 5 for(var j=i+1;j<arr.length;j++){//每次大循环将默认最小数与其后面的所有数相比

算法系列(十四) 狼、羊、菜和农夫过河问题

题目描述:农夫需要把狼.羊.菜和自己运到河对岸去,只有农夫能够划船,而且船比较小,除农 夫之外每次只能运一种东西,还有一个棘手问题,就是如果没有农夫看着,羊会偷吃菜,狼会吃羊. 请考虑一种方法,让农夫能够安全地安排这些东西和他自己过河. 这个题目考察人的快速逻辑运算和短期记忆力.分析一下,在狼->羊->菜这个食物链条中 ,"羊"处在关键位置,解决问题的指导思想就是将"羊"与"狼"和"菜"始终处于隔离状态,也 就是说

[算法系列之二十三]线段树(Interval Tree)

一 背景 在信息学竞赛中,我们经常会碰到一些跟区间有关的问题,比如给一些区 间线段求并区间的长度,或者并区间的个数等等.这些问题的描述都非常简单,但是通常情况下数据范围会非常大,而朴素方法的时间复杂度过高,导致不能在规定时间内得到问题的解.这时,我们需要一种高效的数据结构来处理这样的问题,在本文中,我们介绍一种基于分治思想的数据结构--线段树. 二 简介 线段树是一种二叉树形结构,属于平衡树的一种.它将线段区间组织成树形的结构,并用每个节点来表示一条线段.一棵[1,10)的线段树的结构如图1.1

[算法系列之二十六]字符串匹配之KMP算法

一 简介 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的. 二 基于部分匹配表的KMP算法 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含搜索串"ABCDABD"? 步骤1:字符串"BBC ABC

[算法系列之二十]字典树(Trie)

一 概述 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 二 优点 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高. 三 性质 (1)根节点不包含字符,除根节点外每一个节点都只包含一个字符: (2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串: (3)每个节点的所有子节点包含的字符都不相同. 单词列表为"apps&

算法系列(二十) 计算中国农历(二)

所谓的"天文算法",就是利用经典力学定律推导行星运转轨道,对任意时刻的行星位置进行精确计 算,从而获得某种天文现象发生时的时间,比如日月合朔这一天文现象就是太阳和月亮的地心黄经(视黄 经)差为0的那一瞬间.能够计算任意时刻行星位置的一套理论就被称为星历表,比较著名的星历表有美 国国家航空航天局下属的喷气推进实验室发布的DE系列星历表,还有瑞士天文台在DE406基础上拓展的瑞 士星历表等等.根据行星运行轨道直接计算行星位置通常不是很方便,更何况大多数民用天文计算用不上 那么多精确的轨道参

[算法系列之二十四]后缀树(Suffix Tree)

之前有篇文章([算法系列之二十]字典树(Trie))我们详细的介绍了字典树.有了这些基础我们就能更好的理解后缀树了. 一 引言 模式匹配问题 给定一个文本text[0-n-1], 和一个模式串 pattern[0-m-1],写一个函数 search(char pattern[], char text[]), 打印出pattern在text中出现的所有位置(n > m). 这个问题已经有两个经典的算法:KMP算法 ,有限自动机,前者是对模式串pattern做预处理,后者是对待查证文本text做预处