Table of Contents 1 問題描述 2 問題分析 3 程式碼
1 問題描述
A、B兩座城市相距1000Km,我們有3000個香蕉要從A城市運往B城市,已知一頭大象一次最多能運1000個香蕉, 而且大象每次走1Km要吃掉一個香蕉,如果香蕉被吃完了,大象就不能再繼續往前走。請問,你最終最多能運多少香蕉到B城市。 2 問題分析 當我某一天無意中在網頁上看到這樣的一道題,感慨良多。多年前我在某互連網公司實習的時候,終面時也被問到了一 道同樣的智力題,只是當時題目的描述並不是大象搬香蕉,而是猴子搬香蕉。現在換了下描述對象和參數,換湯不換藥。 回到這道題,問題的關鍵在哪裡呢。先這樣想,如果我們一共只有1000個香蕉,是不是很簡單呢。因為大象每走一Km 要吃掉一個香蕉,而它最多也可以搬動1000個香蕉,我們可以不用往回走,邊走邊吃,走完就吃完了。到目的地後還 剩下0個香蕉……
所以仔細地想一下,問題的關鍵在於,大象並不能一次搬完所有的香蕉,它要走回頭路。而回去的時候也是要消耗香蕉的。 在哪裡返回便是問題的關鍵點。當我們有3000個香蕉的時候,一共得走(2*3-1)=5次,假定我們這時移動的距離為x(3) 當我們只有2000個香蕉的時候,一共得走(2*2-1)=3次,移動的距離為x(2), 當我們只有1000個香蕉的時候, 不用回頭走路(2*1-1)=1次,距離為x(1). 所以,看到規律了吧。
由上面的分析:x(n) = 1000/(2*n-1)1000是大象最多一次能運的香蕉個數, (2*n-1)為每走一公裡所消耗的香蕉個數x(n)為每消耗1000根香蕉,大象能把所有香蕉搬運的公裡數n最大為 3000/1000 = 31000 = x(n) + x(n-1) + ...最後剩下的香蕉數為:3000 - (2*n-1)*x(n) - (2*n-3)*x(n-1)...由於這裡的數字比較簡單,我們口算都能算出來:x(3)= 1000/5 = 200x(2)= 1000/3 = 333.33 多出一個香蕉,不要了,回去取得不償失x(1)= 1000 - 200 - 333 = 467最後剩下的香蕉數為:3000 - 1000 - 1000 - 467 = 533
3 程式碼 有了上面的分析,可以很容易的寫出程式。下面是Python的實現
# -*- coding: utf-8 -*-# n means the count of rounds# It returns the cost of roundsdef cost(per_cost, n): return (2*n - 1) * per_cost# calc how long we could go with cost(n) per kilometerdef f(max_load, per_cost, n): s = max_load / cost(per_cost, n) return s# all_load, the number of all banana # distance, the distance between the cities# max_load, the max loading elephant could carry# per_cost, the cost of banana per KMdef calc_remain(all_load, distance, max_load, per_cost): remain_dist = distance nmax = all_load / max_load all_cost = 0 while nmax > 0: if remain_dist > f(max_load, per_cost, nmax): remain_dist -= f(max_load, per_cost, nmax) all_cost += max_load nmax -= 1 else: all_cost += cost(per_cost, nmax) * remain_dist remain_dist = 0 nmax = 0 print 'Remain load: %d, remain distance %d' % \ ((all_load - all_cost), remain_dist) return (all_load - all_cost), remain_distif __name__ == '__main__': all_load = 3000 distance = 1000 max_load = 1000 per_cost = 1 rload, rdist = calc_remain(all_load, distance, max_load, per_cost)
4 思維擴充
有了上面的程式,我們可以很快地解決這個問題的其它變種。比如說大象至少要能一次搬多少個香蕉才能保證到目的地後 香蕉有剩於。如果問題這樣出的話應該會難一點點。 同樣的,調用我們上面已經寫好的代碼,可以很快地解決這個問題。
if __name__ == '__main__': all_load = 3000 distance = 1000 max_load = 1000 per_cost = 1 for i in range(50, 1000): rload, rdist = calc_remain(all_load, distance, i, 1) if rdist == 0: print "i = %d." % i break
HTML generated by org-mode 6.31a in emacs 23