这是个很经典的问题,但是我看了很多讲解都感觉不是很系统,但是受到了看的讲解的启发,在这里希望写一个比较严谨系统的讲解。
题目是这样的:在漆黑的夜里,四位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,四个人一共只带了一只手电筒,而桥窄得只够让两个人同时通过。如果各自单独过桥的话,四人所需要的时间分别是1,2,5,10分钟;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,你如何设计一个方案,让用的时间最少。(17分钟)
这个问题实际上可以抽象为更一般的问题:N个人过桥,每人需要的时间是t[i],过桥规则不变,求所有人过桥所用的最短时间。
大多数题解是直接写,选两个最快的人,两个最慢的人,然后什么情况选什么方式过桥,然后递归。这样其实缺少理论上的严谨性。很多人会问:为什么选这四个人啊?
好,下面我们就来严谨的分析一下。
首先,下面几句话是显然的:
1.每个人都需要过桥;
2.最慢的两个人过桥后永远不会回来;(因为不会有人需要他们帮着过桥,也不会需要他们送手电筒,当然默认N>=4以保证最慢和最快不重合)
3.最慢的两个人不能两个人独自过桥;(否则就违反了第二条,必须有一个人回来送手电筒)
好,有了上面三句话,我们很容易得到两个推论。
1.要考虑把N个人送过去的最优时间,只需要先考虑怎么把最慢的两个人先送过去的最优时间。(类似于动态规划中的无后效性);
2.既然最慢的两个人不能独自过桥,那必须需要别人的帮助。那么需要谁的帮助呢?显然是最快的人的帮助。最快的几个人呢?讨论呗。(但是可以证明最多不超过两个人,因为假设有第三个人,任何一步他的帮助都没有什么作用)
这样,我们就已经知道为什么要选出这四个人了。现在来分析最优方案。
假设,t[1]~t[N] 是从小到大排好序的。设 A=t[1],B=t[2],C=t[N-1],D=t[N].
现在开始讨论:
1.如果C,D需要一个人的帮助过桥。那么最好的方案肯定是A把C送过去,A回来,A把D送过去,A回来。(A必须要回来,因为这边至少还有个B吧~)
T1=C+A+D+A
2.如果C,D需要两个人的帮助过桥。那么最好的方案肯定是A把B送过去,A回来,C和D过去,B回来。(B必须要回来,因为这边至少还有个A吧~)
T2=B+A+D+B
所以,只需要比较T1和T2的大小就可以确定选择哪一个方案。由公式,显然只需要比较A+C和2*B的大小。
而且,这两个方案的初始状态和终止状态都是一样的,而且选择之后的效果都是,左边的人少了两个。
那么问题就自然的转化为了N-2个人的过桥问题。就是递归的思想。
下面分析一下边界。
如果有三个人A,B,C(由小到大)。显然是用A送C,A回来,A送B。时间T=A+B+C。
如果有两个人。时间就是最大的时间。
一个人。时间就是这个人的时间。
算法详解就到这里。代码可以从网上就可以搜到,可以看一下是不是能看懂了呢?