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