一道有趣的筆試題 水杯量水問題

2021-06-08 15:40:12 字數 1853 閱讀 8082

若干年前,剛進入程式設計行業不久,得到一家公司的筆試機會.其中一題印象深刻:給兩個空量杯,乙個5ml,乙個3ml,加水後,要通過量杯互倒,得到4ml水,求演算法.

之前做過乙個人機對戰的遊戲,接觸到決策樹.看到這道題時,第一感覺應該也是可以用樹形資料結構來解決的.雖然它不屬於博弈類的問題。

最初考慮,以量杯作為樹的結點,在樹中找出一條路徑( 分支 ),使得路徑終結點的當前水量為4ml,那麼問題就得到解決。但仔細考慮,發現這思路有些問題,比如:5ml量杯的水倒入3ml量杯後,再向5ml量杯中倒水,在這棵樹就無法表示。

再仔細分析一下問題,所求演算法的輸出是乙個操作流程。操作流程的每一步都是乙個操作。也就是說,在這個問題中,要提練的資料是"操作",而不是"量杯".

這個問題想清楚後,就好辦了.用樹是對的,只是結點應該是操作而不是量杯.

所有的操作總共有六種:

5->3     表5號量杯倒入3號量杯

3->5     表3號量杯倒入5號量杯

5->e     表將5號量杯的水倒空

3->e     表將3號量杯的水倒空

f->5     表將5號量杯倒滿

f->3     表將3號量杯倒滿

在這棵樹中,每乙個結點,理論上有以上六個操作作為子結點.求解的過程就是在這棵樹中找到一條路徑.使得路徑終結點處,5號量杯中的水為4ml.

再深入考慮:

1. 由於一開始量杯為空,所以只能將f->5或f->3作為決策樹的根結點.

2. 理論上,兩個量杯互倒的操作可以無限進行下去( 比如把 5->3和3->5的操作作為對方的子結點), 因此用深度優先,極有可能導致無限搜尋;另外要得到4ml水這一結果,可以有多種路徑,而所求的往往要求是最優解,所以在樹上的搜尋,只能採用廣度優先的方法.

3. 在量杯互倒的操作中,有一些隱含的約束條件,有助於更快地得到解,這些隱含的約束條件,討論如下:

父結點為 5->3 時,子結點不能為3->5.  ( 同樣 3->5 亦然.)

父結點為 5==e 時( 5號量杯為空 ),子結點不能為 5->3 或 5->e.   ( 同樣 3==e 亦然.)

父結點為 5==f 時( 5號量杯為滿 ),子結點不能為 f->5 或 3->5.    ( 同樣 3==f 亦然.)

4. 在樹的每乙個操作後( 每乙個結點 ),應該標記兩個量杯的當前狀態( e或f ).並且每乙個操作後,記錄5號量杯當前值.

5. 樹搜尋演算法,採用遞迴函式.當5號量杯當前值為4時,說明操作成功,返回true.回溯法,遞迴函式需要返回值.

至此,問題得到解決.

總結以上的思考過程可知:

在面對實際問題時,有時如何提練資料,或者說把什麼作為待處理的資料,成為解決問題的關鍵.一般先明確輸出結果,然後,從要求解的結果,或者說輸出結果倒過來分析,會比較有效.

而資料結構,也完全是根據如何方便要解決的問題,根據演算法的需要來選擇的.在學習資料結構時,為了方便理解,待處理資料在邏輯結構上本身就與所要講解的資料結構相匹配.而在使用時,資料結構有時並不用來反映資料直觀的客觀邏輯結構,而是為了更好的求解問題,為了滿足演算法需要的一種選擇。( 當然也可以說,這樣選擇出來的資料結構,反映了資料間的另一種關係.)

再比如,對一列資料的排序操作,其輸入與輸出的資料都是線性邏輯結構。對於選擇排序和插入排序來說,通過構建陣列( 線性邏輯結構 )就可以實現;而構建二叉樹也可以實現對無序數列的排序操作。( 其實,本文討論的量杯倒水問題,輸出結果也是乙個線性邏輯結構。)

也就是說,輸入輸出無法決定運算中究竟要選擇哪種資料結構;資料自身客觀的邏輯結構,也無法左右運算中要選擇哪種資料結構;只有演算法本身的需要才能決定要選擇哪種資料結構。

另外:人機對弈的問題,一般會把棋盤上當前局面作為乙個結點。與此類似,如果把每一次倒水結束後,兩個杯子中所盛水量的狀態作為乙個結點,應該也可以求得問題的解。按這種方法得到的演算法又會是怎樣的呢?

一道筆試題

看到一道筆試題,跟自己想的有點出入,就跑了下,看了看原因。我稍微改了下 include int main int argc,char argv 輸出結果 c 5 d 245 press any key to continue vc6.0 debug下的彙編 5 unsigned char a 0xa...

一道筆試題

上次去筆試的時候,有一道題,怎麼也沒做出來,當時也是很緊張,有些思路,但卻沒有做出來。有四個人要過乙個獨木橋,因為天比較黑,而且橋只能允許兩個人同時通過,並且他們只有乙個手電筒。四個人單獨同時橋的時間是1,2,5,8分鐘。問最短的時間是多少?當時我的答案 1和8,1回來,1 5,1回來,1 2 8 ...

一道筆試題

題目是這樣的 判斷乙個小於1000的正整數是否為素數。素數的定義就不說了,以下直接分析解法,畢竟是在寫與專業相關的東西,是給本專業的人看得,所以看的人應該有點基礎吧?求素數的問題是乙個數學上的難題,這是常識,但是本題目限制了最大範圍是在1000以內,所以就可以嘗試找出乙個足夠好的解了。首先給出乙個最...