讨论!经典问题——骆驼运输香蕉的问题

JebySin 2010-10-11 10:21:44
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。

最近,我一有空就在考虑这个问题,不知道为什么网上有人说是那个答案呢?他们是用数学方法求出来的?只是我数学不好,实在没办法理解,所以,我想通过程序来解决这个问题。我考虑过,这个问题用程序来解决,有两种方法。
第一种方法,先从问题抽象出数学模型,利用函数,方程之类的来列出最优解的算式,然后用程序代码来实现这些算式,计算出最优解;
第二种方法,不从数学角度考虑,直接写程序模拟骆驼运输香蕉的过程,将每种可行的运输方案的结果保存在一个数组里,最后选出最优答案。
我数学不及格,从第二种方法考虑了,各位有什么高见呢?
希望各位一起来讨论这个问题,同时,我们一起试着用程序来解决这个问题,把代码贴上来,看谁的代码更优雅简洁。

汗……我都弄晕了,那位高手来帮忙分析一下,这样模拟行不行?

...全文
2240 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
libertatis 2011-01-09
  • 打赏
  • 举报
回复
这时候可能又出现另外一个问题,就是在最开始出发时,第一只香蕉是什么时候给骆驼吃的。题目说没有香蕉,骆驼是不肯走的。所以说应该是出发时给它吃的,而不是走1公里后给它吃的。也就是说可以在533公里处出发时,先给骆驼吃一只香蕉,让它驮1000只香蕉。最后到达目的地时,应该剩下534只香蕉。
libertatis 2011-01-09
  • 打赏
  • 举报
回复
[Quote=引用楼主 jebysin 的回复:]
……
(下面是第三步,这题考的难点就在这里。下面的方法是关键。)
在533公里处剩有1001根香蕉。这时,扔掉一根香蕉,直接运1000根到终点。
……
[/Quote]
在533公里处剩下1001只香蕉。那么为什么要在533公里处扔掉1只香蕉呢?你凭什么要扔掉一只香蕉呢?题目不是说了吗,“……骆驼每一次只能带1000只香蕉,而且每一公里吃一只香蕉,没有香蕉吃,它是不肯走的……”,你可以在533公里处出发时,让骆驼驮1000只香蕉,剩下的一个给它吃,这样到达目的地时就剩下534只香蕉了。如果你要是扔掉一只香蕉,让它驮1000只想香蕉,那么从533公里处出发时,你不是还得要给它吃一只香蕉吗?那么,这时出发时,骆驼实际上驮的是999只。那么你扔的那一只香蕉就是没有意义的。
凉岑玉 2010-10-14
  • 打赏
  • 举报
回复
最快又最省香蕉的方法就是把骆驼卖了··可以买两匹马以及马良··只用两次拉运就搞定··
precious 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 tghlsy1234567890 的回复:]
文字说明:
首先将3000只香蕉运送到X1公里处,一共需要吃掉【5*X1】(在X1距离上共运行了5次)只香蕉。剩余香蕉为【3000-5*X1】。
此处X1的选择为:使剩余香蕉数<=2000。X1=200。剩余香蕉2000,剩余800公里

再将2000只香蕉运送到X2公里处,一共需要吃掉【3*X2】(在X1距离上共运行了3次)只香蕉。剩余香蕉为【2000-3*X2】。
此处X2的选择为:使剩余香蕉数>=1000并且最接近1000。X2=333。剩余香蕉1001,剩余467公里。

在距离终点467公里处驮上1000之香蕉出发,最后剩余:1000-467=533。
[/Quote]
/**
* 取得剩余香蕉最大值<br>
* @param total 香蕉总数
* @param max 每次最多运输数量
* @param distance 总路程
* @since
*/
private static void getMax(int total,int max,int distance){
int remainT = total;//剩余香蕉总数
int remainD = distance;//剩余总路程
int pos = 0;
int cycle = (remainT / max) * 2 -1;
while(cycle > 1){
pos = max / cycle;
remainD-=pos;
remainT = remainT - pos * cycle;
System.err.println("剩余公里:" + remainD + "剩余香蕉:" + remainT);
cycle = (remainT / max) * 2 -1;
//在此处加上一句就可以了
//剩余香蕉减去每次最多运输量 x = (remainT - max)之后当这个数值在3~max之间时,执行下面语句
//x如果等于3 即骆驼一次拿满1000根走到一公里处放下998根 回头去取剩下的3根,这事骆驼在消耗两根,
//还剩下2+998=1000
if ((remainT - max) >= 3 && (remainT - max) < max) {
System.err.println("最终剩余香蕉:"+ (max - remainD + ((remainT - max) / 3)));
}
}
System.err.println("最终剩余香蕉:" + (max - remainD));
}
杰必尚 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 qingtianliuyun 的回复:]
在敲了一天键盘后,看到了这个题目。。。。头都大了
[/Quote]
呵呵……今天不行,那改天再说啊
qingtianliuyun 2010-10-14
  • 打赏
  • 举报
回复
在敲了一天键盘后,看到了这个题目。。。。头都大了
杰必尚 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 cenhuineng 的回复:]
最快又最省香蕉的方法就是把骆驼卖了··可以买两匹马以及马良··只用两次拉运就搞定··
[/Quote]
一头骆驼换两匹马……高明
yexiongMYBH 2010-10-13
  • 打赏
  • 举报
回复
面试题神马的,最讨厌了。
liuyuhua0066 2010-10-13
  • 打赏
  • 举报
回复
骆驼表示它不喜欢吃banana
杰必尚 2010-10-13
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zhangbaohua505 的回复:]
三楼的算法不准确,针对本题是可以计算的,要考虑当剩余香蕉总数(remainT)大于每次最多运输数量(max)并且这个数大于等于3的情况判断(remainT-max)是3的几倍,(max - remainD)在加上这个倍数就是最后剩余香蕉的总数。
[/Quote]
期待你的答案
杰必尚 2010-10-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 tghlsy1234567890 的回复:]
文字说明:
首先将3000只香蕉运送到X1公里处,一共需要吃掉【5*X1】(在X1距离上共运行了5次)只香蕉。剩余香蕉为【3000-5*X1】。
此处X1的选择为:使剩余香蕉数<=2000。X1=200。剩余香蕉2000,剩余800公里

再将2000只香蕉运送到X2公里处,一共需要吃掉【3*X2】(在X1距离上共运行了3次)只香蕉。剩余香蕉为【2000-3*X2】。
此处X2的选择为:……
[/Quote]
现在我也开始相信这个就是最佳答案了。
昨天下午我一直在试着用程序来模拟这个过程,始终模拟不出来……最后晚上的时候,我在纸上画图分析,理解了533这个结果是怎么得来的……
在这里,对这个问题总结一下,希望对研究这个问题和对上述答案不理解的朋友一些启示:
1.骆驼肯定每次尽量多地运载香蕉;
2.骆驼运载着香蕉往B地赶路的路途中,因为会消耗身上的香蕉,所以应该尽量将放在中途的香蕉拾起来放入背包。
3.骆驼返回的时候应该尽量少带香蕉而吃放在中途的香蕉。
precious 2010-10-13
  • 打赏
  • 举报
回复
三楼的算法不准确,针对本题是可以计算的,要考虑当剩余香蕉总数(remainT)大于每次最多运输数量(max)并且这个数大于等于3的情况判断(remainT-max)是3的几倍,(max - remainD)在加上这个倍数就是最后剩余香蕉的总数。
折腾的生活 2010-10-13
  • 打赏
  • 举报
回复
一公里一吃,这骆驼不行啊!还这么爱吃香蕉,是不是跟猴子杂交春来的啊?
zxrjswx 2010-10-13
  • 打赏
  • 举报
回复
要好好考虑一下
sustbeckham 2010-10-13
  • 打赏
  • 举报
回复
骆驼表示,我有驼峰,不用吃东西。
precious 2010-10-13
  • 打赏
  • 举报
回复
收藏了 仔细研读啊 呵呵
24K純帥 2010-10-13
  • 打赏
  • 举报
回复
俺也同求解释
MyOracleX 2010-10-13
  • 打赏
  • 举报
回复
很好,先收藏了,下班后仔细研究一下
tghlsy1234567890 2010-10-13
  • 打赏
  • 举报
回复
文字说明:
首先将3000只香蕉运送到X1公里处,一共需要吃掉【5*X1】(在X1距离上共运行了5次)只香蕉。剩余香蕉为【3000-5*X1】。
此处X1的选择为:使剩余香蕉数<=2000。X1=200。剩余香蕉2000,剩余800公里

再将2000只香蕉运送到X2公里处,一共需要吃掉【3*X2】(在X1距离上共运行了3次)只香蕉。剩余香蕉为【2000-3*X2】。
此处X2的选择为:使剩余香蕉数>=1000并且最接近1000。X2=333。剩余香蕉1001,剩余467公里。

在距离终点467公里处驮上1000之香蕉出发,最后剩余:1000-467=533。

代码:
/**
* 取得剩余香蕉最大值<br>
* @param total 香蕉总数
* @param max 每次最多运输数量
* @param distance 总路程
* @since
*/
private static void getMax(int total,int max,int distance){
int remainT = total;//剩余香蕉总数
int remainD = distance;//剩余总路程
int pos = 0;
int cycle = (remainT / max) * 2 -1;
while(cycle > 1){
pos = max / cycle;
remainD-=pos;
remainT = remainT - pos * cycle;
System.err.println("剩余公里:" + remainD + "剩余香蕉:" + remainT);
cycle = (remainT / max) * 2 -1;
}
System.err.println("最终剩余香蕉:" + (max - remainD));
}

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧