There are 1000 buckets, one and only one of them contains poison, the rest are filled with water. They all look the same. If a pig drinks that poison it will die within 15 minutes. What is the minimum amount of pigs you need to figure out which bucket contains the poison within one hour.
Answer this question, and write an algorithm for the follow-up general case.
Follow-up:
If there are n buckets and a pig drinking poison will die within m minutes, how many pigs (x) you need to figure out the "poison" bucket within p minutes? There is exact one bucket with poison.
這道題博主拿到以后並木有什么頭緒,可是明明標的是Easy,打擊甚大,於是去論壇上大神們的解法,感覺這道題應該算是一道Brain Teaser的題,對問題的分析能力要求很高。那么我們來一步一步從最簡單的情況來分析吧,假設只有1只豬,只有15分鍾,那么我們能測幾個水桶呢?很顯然是兩個,因為只能測一次的話,讓豬去隨便喝一桶,如果毒死了,就是喝的那桶,反之則是另一桶。好,那么如果有兩只豬呢,能測幾桶?怎么喝呢,兩只豬一豬喝一桶,再同時喝一桶,剩下一桶誰也不喝,那么如果兩只豬都毒死了,說明是共同喝的那桶有毒,如果某個豬毒死了,說明該豬喝的那桶有毒,如果都沒事,說明是誰也沒喝的那桶。那么我們應該看出規律了吧,沒錯,三豬能測8桶,其實就是2的指數倍。
如果只能測一次的話,實際上相當一個一維數組,而如果能測兩次的話,情況就不一樣了,我們就可以重復利用豬了。比如還是兩只豬,能測兩次,功能測幾個桶,答案可以測9桶,為啥,我們組個二維數組:
1 2 3
4 5 6
7 8 9
如果我們讓第一頭豬第一次喝1,2,3桶,第二次喝4,5,6桶,而讓第二頭豬第一次喝1,4,7桶,第二次喝2,5,8桶,我們可以根據豬的死亡情況來確定是哪一桶的問題,實際上就把豬被毒死的那個節點當作了二維數組的橫縱坐標來定位毒桶的位置,巧妙吧~更巧妙的是,如果再增加一頭豬,實際上是給數組增加一個維度,變成了一個三維數組,那么三只豬,測兩次,可以測27桶,叼不叼。這道題讓我們求最少用多少豬來測,那么就是求數組的維度,我們知道了數組的總個數,所以要盡量增加數組的長寬,盡量減少維度。這里,數組的長寬其實都是測試的次數+1,所以我們首先要確定能測的次數,通過總測試時間除以毒發時間,再加上1就是測試次數。有了數組長寬m,那么如果有x只豬,能測的桶數為m的x次方,現在我們給定了桶數N,要求x,就log一下就行,然后用個換底公式,就可以求出x的值了,參見代碼如下:
class Solution { public: int poorPigs(int buckets, int minutesToDie, int minutesToTest) { return ceil(log(buckets) / log(minutesToTest / minutesToDie + 1)); } };
參考資料:
https://discuss.leetcode.com/topic/67666/another-explanation-and-solution
https://discuss.leetcode.com/topic/67482/solution-with-detailed-explanation