讨论!经典问题——骆驼运输香蕉的问题
A地有3000只香蕉,现在,需要将这批香蕉用一只骆驼运输到B地。A地到B地的路程是1000公里,骆驼每一次只能带1000只香蕉,而且每一公里吃一只香蕉,没有香蕉吃,它是不肯走的。请问:如何做到最有效率地运输最多的香蕉到B地呢?
问题看上去就这么简单,听说是微软的面试题,相信不少朋友之前都看到过或者看过类似的问题。网上也有这个问题的答案,随便一搜索,就可以看到一个似乎很清晰明了的答案。
但是,我想跟大家讨论的是网上的答案没有足够的理由让人信服那就是最佳运输方案。这里顺便我把网上流传的答案给大家看看。
参考答案一:
第一步,骆驼必定在起点分三次驮,每次驮1000只香蕉,那么从中间停留点就要来回5次。骆驼先驮1000只香蕉起程,每隔一公里放下4根香蕉(这是骆驼后面来回需要吃掉的香蕉),再加上自身消耗一公里1根的,这样可以走1000/5=200公里,回来的时候就靠吃前面放下4根香蕉中的一根,这样第一次行程结束返回起点时,那200公里的路段,每公里都有三根香蕉。
第二步,这时除去放在路上给骆驼吃的香蕉,还有2000只,骆驼需要再回来驮一次所以是来回3次。骆驼再驮1000只起程,先走的200公里消耗第一次行程放下的香蕉(这时候每公里还剩两根了),过了200公里后继续前进,每隔一公里放下2根香蕉(再回来驮需要吃掉的),再加上自身消耗一公里1根的,这样可以再走1000/3=333公里,回来的时候就吃第一次行程和第二次行程放下的香蕉。
第三步,这时候可以看到在0到533公里的路程内每公里都有一根香蕉,这样骆驼可以靠消耗路边的香蕉前行,而不用吃自身的1000根香蕉,那么到目的地的时候可以剩下1000-(1000-533)=533根香蕉。
参考答案二:
先让骆驼运1000根到200公里处,吃掉了200根,剩800,放下600根,带200回去起点吃。再运1000根到200公里,吃200根,剩800,再放下600根,带200回去路上吃。再运起点剩下的1000根,运到200公里处,剩800根,加上前两次放下的600根,一共有2000根在200公里处。
(上面所说的是第一步,把3000根香蕉减少到2000根,运了200公里。之后就不用运三次,只需运两次。而且,下面的第二步是要把2000根减少到1000根。这样就不用运两次,直接运1000到终点。)
在200公里处有2000根香蕉。先运1000根走333公里,也就是运到全程的533公里处(200公里+333公里)。吃掉333根,剩667根,放下334根,带333回程吃(回200公里处)。再在200公里处运剩下的1000根,也是运到533公里处。吃掉333根,剩667根。加上前一次放下的334根,共1001根。
(下面是第三步,这题考的难点就在这里。下面的方法是关键。)
在533公里处剩有1001根香蕉。这时,扔掉一根香蕉,直接运1000根到终点。因为剩下路程为:1000公里减533公里等于467公里,所以骆驼要吃掉467根香蕉。运1000根,吃掉467,1000-467=533 根。所以到终点后剩下533根香蕉。也就是说,在533公里处扔掉的那一根香蕉在一开始的起点处就可以不运的。在起点只需运两次1000,一次999。
最近,我一有空就在考虑这个问题,不知道为什么网上有人说是那个答案呢?他们是用数学方法求出来的?只是我数学不好,实在没办法理解,所以,我想通过程序来解决这个问题。我考虑过,这个问题用程序来解决,有两种方法。
第一种方法,先从问题抽象出数学模型,利用函数,方程之类的来列出最优解的算式,然后用程序代码来实现这些算式,计算出最优解;
第二种方法,不从数学角度考虑,直接写程序模拟骆驼运输香蕉的过程,将每种可行的运输方案的结果保存在一个数组里,最后选出最优答案。
我数学不及格,从第二种方法考虑了,各位有什么高见呢?
希望各位一起来讨论这个问题,同时,我们一起试着用程序来解决这个问题,把代码贴上来,看谁的代码更优雅简洁。
汗……我都弄晕了,那位高手来帮忙分析一下,这样模拟行不行?