園子裡有朋友提到這個問題,相信各位都見過這種題,有時面試也會碰到。
解題方法有很多,有人靠猜、窮舉、倒推,在倒水次數很多的情況下,就會比較麻煩了。
早些年的時候我得出了一種通用而簡單的解此類題目的方法。
以乙個5公升乙個6公升杯子倒3公升水為例,這兩個杯子根據裝的水量不同,共有22種狀態,而加水倒水的過程就是在這些狀態之間切換的過程,兩個杯子都是空的是初始狀態,其中有乙個杯子的水是3陞是最終狀態,所以這個問題可以用有限狀態機來解決。為了直觀起見,把這些狀態根據兩個杯子的水量分布在二維**中,於是乎得出了下面這個圖:
圖中:橫座標表示乙個杯子(a)的水量,縱座標表示另乙個杯子(b)的水量,灰色框表示不存在的狀態,黃色框表示初始狀態,藍色框表示最終狀態。
下面就是如何在這些狀態中進行切換了。首先,可以把某個杯子加滿水,在圖中則表示為從零狀態越過灰色區域跳到對面的滿狀態,把b杯子加滿就是從上下到,如圖2,把a杯子加滿就是從左到右,如圖3。
把某個杯子倒空,則方向相反,圖略。
將水從某個杯子倒進另乙個杯子則可以用從原狀態向左下或右上方向的45度線表示,目標狀態就表示倒入的量和原杯剩餘的量。如圖4表示將盛有4l水的a杯子中的水倒入b杯,倒完後b杯水有4l,a懷為空。圖5表示a杯滿,b杯1l,從a杯倒入b杯後,b杯滿,a杯剩2l。圖6表示a杯1l,b杯滿,將b杯倒入a杯後,a杯滿,b杯空。這些都是允許的狀態變化。變化的原則就是只能在左下倒右上的45度方向上,因為在這個方向上的變化,水總量是不變的。
現在,得出了幾種允許的變化,看能不能從初始狀態沿著這樣的線到達最終狀態。
一開始,就有兩種選擇,先試試向右吧。得到圖7。
接下來只有兩種選擇,向左下或者向下,向下就是都倒滿,接下來的操作只能再倒空乙個杯子,沒什麼意義,所以只有一種選擇,向左下,到(1,5),得到圖8。
接下來有兩種選擇,顯然,再回去以及向右都是沒有意義的,所以只有一種選擇,那就是向上到(1,0),得到圖9。
同樣的,向右的目的地已經走過了,那麼向左下,得圖10。
按這樣的思路,最終可以得到圖11。達到了最終狀態。
這裡得出的解就是:
1、a加滿(6,0)
2、a倒b(1,5)
3、b倒空(1,0)
4、a倒b(0,1)
5、a加滿(6,1)
6、a倒b(2,5)
7、b倒空(2,0)
8、a倒b(0,2)
9、a加滿(6,2)
10、a倒b(3,5)(得到3l)
如果一開始先向下也就是先加滿b,結果也是比較類似的。
如果到達某個狀態,找不到下一步,或者所有下一步都會回到以前曾經到達過的狀態,則無解。
在兩個杯子的情況下,除第一步外基本沒有可多選的分支。
如果在多個杯子的情況下,則用多維距陣來表示狀態,而可選分支也會隨維度增加而增加,形成搜尋樹,各位可以自己進一步進行探索。
posted on
2009-09-22 12:50
...)
編輯 收藏
關於杯子量水的一種演算法
題目 有兩個水罐a,b,容量分別為x,y,均為不小於1的整數,在沒有任何刻度記號的下,可以量出那些數量單位的水 輸入示例 4 3輸出示例 1 2 3 4 5 6 7 輸入示例2 1 2輸出示例2 1 2 3 演算法 以乙個5公升乙個6公升杯子倒3公升水為例,這兩個杯子根據裝的水量不同,共有22種狀態...
3種解法 兩水壺拼水問題
有兩個容量分別為 x公升 和 y公升 的水壺以及無限多的水。請判斷能否通過使用這兩個水壺,從而可以得到恰好 z公升 的水?如果可以,最後請用以上水壺中的一或兩個來盛放取得的 z公升 水。你允許 示例 1 from the famous die hard example 輸入 x 3,y 5,z 4 ...
C 有問題的里程數通用解法
題目描述 某輛汽車有乙個里程表,該里程表可以顯示乙個整數,為該車走過的公里數。然而這個里程表有個毛病 它總是從3變到5,而跳過數字4,里程表所有位 個位 十位 百位等 上的數字都是如此。例如,如果里程表顯示339,汽車走過1公里之後,該里程表顯示350。輸入輸入乙個整數num,表示里程表顯示的數值,...