日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《吃豆子过桥问题》——经典智力题、面试题

發布時間:2024/1/1 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《吃豆子过桥问题》——经典智力题、面试题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載http://www.cnblogs.com/webary/p/4827688.html?utm_source=tuicool&utm_medium=referral

吃豆子過橋問題

  本題來自于百度校招面試題,通過一個簡單的智力問題理解遞歸問題的解法。

  一:問題描述

  一個人要過一座80米的橋,每走一米需要吃一顆豆子,他最多可以裝60顆豆子,問最少需要吃多少顆豆子才能走完橋?

?

  二:初步分析

  1.一趟(不折回)最多只能走60米豆子就會被吃完;

  2.如果有折回,必須保證能夠返回到有豆子的地點,且在折回點放下的豆子盡量多;

  3.盡可能少的折回(次數和折回的距離都要少,畢竟一趟折回就要多消耗一個來回的豆子);

  4.折回點的豆子數量要求至少能夠走完剩余的部分;

?

  三:具體分析

  1.由條件1得一趟走不完,由條件3我們可以考慮折回盡量少的次數能否走完。

  先考慮只折回一次,那么此時就要求得折回點的位置。

  2.由條件3得折回的距離盡量短,那么可以考慮最短的折回距離,很明顯應該是20米處;設折回點距離起始位置x米,則此時x=20;那么在x處,需要至少有60顆豆子,一次性拿60顆豆子走完最后一程。

  那么問題就來了,怎么在x處囤積60顆豆子呢,假使他第一次信心滿滿的拿著60顆豆子,走到x處就只剩下40顆了,現在不夠走完剩余的全程啊,只能放下一部分折回去再取了,那放多少呢,很明顯由條件2得我們需要放下20顆,拿著20顆剛好可以折回到起點,繼續拿著60顆豆子第二次來到x處,此時手上還有40顆,再撿起第一次放的20顆,共60顆豆子剛好可以走完全程。

  在這種情況下,我們易知,他共走了(20*3+60=?120米,故吃掉120顆豆子。

?

  四:問題拓展

  如果橋長81米呢?

  此時我們如果還是只折回一次的話,在21米處還是得有60顆豆子,也就是需要搬運60顆豆子到21米處;分析得不可能只折回一次就搬運60顆豆子到21米處,因此需要再設置一個折返點y,此時x=210<y<x

  剛才考慮了80米的情況,那么我們可以假設現在在80米的基礎上加了1米,因此可以設y=1,即先折回兩趟到1米處,這樣y處就有60*3-5*(1)=175顆豆子,再從yx折返1趟,x處就有60*2-3*(20)=60顆豆子,最后從x出發拿著60顆豆子就可以愉快的走過橋了。

  因此他共走過5*(1)+3*(20)+(60)?=?125米,故吃掉125顆豆子。

?

  五:再次拓展

  如果橋長n米,最多裝m顆豆子,最少消耗f(n,m)nm的關系是什么呢?

  此時問題突然就變得很復雜了,別急,我們分析一下剛才的思路,橋長從80米到81米,就是要在1米處放足夠多豆子(當然只要不小于橋長80米時的消耗就行),那么這些豆子又需要從起點處運到1米處,那么在這1米內又需要消耗多少豆子呢?

  我們可以考慮先把可裝的最大豆子數m固定(假設還是60),當橋長0<n<=60米時,f(n,m)?=?n

  當n=61時,需要在1米處囤積f(n-1,6)f(60,60)=60顆豆子,囤積過程中需要往返一次,第一次到達1米處留下58顆豆子趕緊回去再取60顆到達1米處還剩59顆,現在有117顆足夠走完最后60米。消耗豆子1*2+(1)+60?=?63顆豆子;

  當n=62時,需要在1米處囤積f(n-1,m)f(61,60)=63顆豆子,囤積過程中需要往返一次,第一次到達1米處留下58顆豆子趕緊回去再取60顆到達1米處還剩59顆,現在有117顆足夠走完最后61米。消耗豆子1*2+(1)+63?=?66顆豆子;

  以此類推...

  那么問題來了,細心的你肯定發現了上面那種情況都是往返一次的,但是不是每次都只往返一次,比如當n=81時,該怎么確定往返的次數呢?

  分析上面的遞推關系我們可以知道,每次往返的趟數與f(n-1,m)的大小有關。分析往返過程易知:最后一次到達1米處剩59顆豆子,之前每次到達1米處可以放下58顆豆子,假設之前到達了1米處T次,則有:

  59?+?58?*?T?>=?f(n-1,60)??==>??T?>=?[f(n-1,60)-59]/58

  由于T必須是整數,故T?=?ceil((f(n-1,60)-59)?/?58)ceil(x)表示對x向上取整,即不小于x的最小整數

  另一種表示方式為T?= floor( (f(n-1,60)-2)?/?58 ),這種寫法是為了方便編程實現,整型數的除法會自動向下取整

  之前往返T次消耗掉2T顆豆子,最后一次到達1米處消耗1顆豆子,故總消耗:f(n-1,60)?+?2T?+?1顆豆子

  這時候我們考慮將固定為60m擴展為任意m,則有:f(n,m)?=?f(n-1,m)?+?ceil(?f(n-1,m)-(m-1))?/?(m-2)?)?*?2+?1?=?f(n-1,m)?+?(f(n-1,m)-2)?/?(m-2)?*?2+?1?;

  好了到這里,這個問題也徹底解決完了,現在就讓我們用簡短的代碼來實現這個過程吧!

?

  六:編程實現?  

1 #include<cmath> 2 #include<iostream> 3 using namespace std; 4 typedef unsigned long long int64; 5 6 //參數說明:length為橋的長度,maxNum為最大可帶的豆子數 7 //遞歸實現 8 int64 getMinConsume(int length, int maxNum) { 9 if(length <= maxNum) 10 return length; 11 int64 get_n_1 = getMinConsume(length-1,maxNum); //上一次的豆子消耗 12 return get_n_1 + (get_n_1-2)/(maxNum-2) * 2 + 1; 13 } 14 //第二種公式實現——遞歸 15 int64 getMinConsume2(int length, int maxNum) { 16 if(length <= maxNum) 17 return length; 18 int64 get_n_1 = getMinConsume2(length-1,maxNum); //上一次的豆子消耗 19 return get_n_1 + ceil((double)(get_n_1-maxNum+1)/(maxNum-2)) * 2 + 1; 20 } 21 //非遞歸的實現方式 22 int64 getMinConsume_NoRecursive(int length, int maxNum) { 23 if(length <= maxNum) 24 return length; 25 int64 result = maxNum, i; 26 for(i=maxNum; i<length; i++) 27 result += (result-2)/(maxNum-2) * 2 + 1; 28 return result; 29 } 30 31 int main() 32 { 33 int maxNum=60, length; 34 for(length=50; length<201; length++) 35 cout<<length<<"米至少消耗"<<getMinConsume2(length,maxNum)<<"顆豆子!"<<endl; 36 return 0; 37 } 38 39 int main2() 40 { 41 while(1){ 42 cout<<"請輸入最大可帶的豆子數量和橋的長度: "; 43 int maxNum, length; 44 if(!(cin>>maxNum>>length)) 45 break; 46 cout<<"至少消耗"<<getMinConsume_NoRecursive(length,maxNum)<<"顆豆子!"<<endl; 47 } 48 return 0; 49 }

  最后,感謝百度三面面試官耐心的引導我思考這道題,并不斷加大難度把這道題理解透徹,還監督我完成代碼的實現,在此謝謝溫和友善的劉面試官~

  更多關于百度校招面試經歷請參見:百度校招面試經歷及總結(全部通過等offer中)

總結

以上是生活随笔為你收集整理的《吃豆子过桥问题》——经典智力题、面试题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。