一道有趣的笔试题( 水杯量水问题 )
来源:互联网 发布:网络写手的收入 编辑:程序博客网 时间:2024/04/29 09:26
若干年前,刚进入编程行业不久,得到一家公司的笔试机会.其中一题印象深刻:给两个空量杯,一个5ml,一个3ml,加水后,要通过量杯互倒,得到4ml水,求算法.
之前做过一个人机对战的游戏,接触到决策树.看到这道题时,第一感觉应该也是可以用树形数据结构来解决的.虽然它不属于博弈类的问题。
最初考虑,以量杯作为树的结点,在树中找出一条路径( 分支 ),使得路径终结点的当前水量为4ml,那么问题就得到解决。但仔细考虑,发现这思路有些问题,比如:5ml量杯的水倒入3ml量杯后,再向5ml量杯中倒水,在这棵树就无法表示。
再仔细分析一下问题,所求算法的输出是一个操作流程。操作流程的每一步都是一个操作。也就是说,在这个问题中,要提练的数据是"操作",而不是"量杯".
这个问题想清楚后,就好办了.用树是对的,只是结点应该是操作而不是量杯.
所有的操作总共有六种:
5->3 表5号量杯倒入3号量杯
3->5 表3号量杯倒入5号量杯
5->E 表将5号量杯的水倒空
3->E 表将3号量杯的水倒空
F->5 表将5号量杯倒满
F->3 表将3号量杯倒满
在这棵树中,每一个结点,理论上有以上六个操作作为子结点.求解的过程就是在这棵树中找到一条路径.使得路径终结点处,5号量杯中的水为4ml.
再深入考虑:
1. 由于一开始量杯为空,所以只能将F->5或F->3作为决策树的根结点.
2. 理论上,两个量杯互倒的操作可以无限进行下去( 比如把 5->3和3->5的操作作为对方的子结点), 因此用深度优先,极有可能导致无限搜索;另外要得到4ml水这一结果,可以有多种路径,而所求的往往要求是最优解,所以在树上的搜索,只能采用广度优先的方法.
3. 在量杯互倒的操作中,有一些隐含的约束条件,有助于更快地得到解,这些隐含的约束条件,讨论如下:
父结点为 5->3 时,子结点不能为3->5. ( 同样 3->5 亦然.)
父结点为 5==E 时( 5号量杯为空 ),子结点不能为 5->3 或 5->E. ( 同样 3==E 亦然.)
父结点为 5==F 时( 5号量杯为满 ),子结点不能为 F->5 或 3->5. ( 同样 3==F 亦然.)
4. 在树的每一个操作后( 每一个结点 ),应该标记两个量杯的当前状态( E或F ).并且每一个操作后,记录5号量杯当前值.
5. 树搜索算法,采用递归函数.当5号量杯当前值为4时,说明操作成功,返回true.回溯法,递归函数需要返回值.
至此,问题得到解决.
总结以上的思考过程可知:
在面对实际问题时,有时如何提练数据,或者说把什么作为待处理的数据,成为解决问题的关键.一般先明确输出结果,然后,从要求解的结果,或者说输出结果倒过来分析,会比较有效.
而数据结构,也完全是根据如何方便要解决的问题,根据算法的需要来选择的.在学习数据结构时,为了方便理解,待处理数据在逻辑结构上本身就与所要讲解的数据结构相匹配.而在使用时,数据结构有时并不用来反映数据直观的客观逻辑结构,而是为了更好的求解问题,为了满足算法需要的一种选择。( 当然也可以说,这样选择出来的数据结构,反映了数据间的另一种关系.)
再比如,对一列数据的排序操作,其输入与输出的数据都是线性逻辑结构。对于选择排序和插入排序来说,通过构建数组( 线性逻辑结构 )就可以实现;而构建二叉树也可以实现对无序数列的排序操作。( 其实,本文讨论的量杯倒水问题,输出结果也是一个线性逻辑结构。)
也就是说,输入输出无法决定运算中究竟要选择哪种数据结构;数据自身客观的逻辑结构,也无法左右运算中要选择哪种数据结构;只有算法本身的需要才能决定要选择哪种数据结构。
另外:
人机对弈的问题,一般会把棋盘上当前局面作为一个结点。与此类似,如果把每一次倒水结束后,两个杯子中所盛水量的状态作为一个结点,应该也可以求得问题的解。按这种方法得到的算法又会是怎样的呢?
- 一道有趣的笔试题( 水杯量水问题 )
- 一道有趣的笔试题
- 一道有趣的笔试题
- 一道有趣的笔试题目!
- 一道很有趣的关于printf的笔试题
- 阿里巴巴一道笔试题【程序中错误量的估算】
- 一道有趣的题
- 有趣的一道题
- 一道有趣的智能问题
- 一道有趣的木板问题
- [笔试题] 两个有趣的问题
- 一道简单有趣的java题:输出顺序的问题
- 很有趣的一道编程题,子弹分发问题
- 一道有趣的java题
- 一道有趣的算法题
- 一道有趣的sql题
- 一道有趣的sql题
- 一道有趣的算法题
- 揭开隐藏数据的面纱,优化应用程序性能
- 我要学ASP.NET MVC 3.0(十四): MVC 3.0 实例系列之创建数据表格
- python实现网络爬虫
- SQL Server数据库,必须启动项
- Android 部分内容设置颜色、字体、超链接、图片
- 一道有趣的笔试题( 水杯量水问题 )
- 观察者模式
- 阻塞与非阻塞I/O
- python中线程的使用
- 深入C++的new【好文转载】
- jsp---->jsp执行过程
- linux socket 编程(C语言)
- 新手:Struts2.0.9部署后启动Tomcat6报错解决
- Android 中的menu以及自定义menu