一道好玩的邏輯推理題(和真話及假話相關)

  前幾天在博客堂(http://blog.joycode.com)的主頁上看到一道非常有意思的題目。題目如下:

    話說某個小島上的居民有兩個部落,一個部落的人只說真話,另一個的人有時候說真話,有時候說假話。(聽上去很熟吧?)島上的每個人都知道其他人的真實身份(怎麼知道的?別問我,呵呵)
現在知道島上共有2005人,真話部落比不一定部落的人多。如果你是島上的新任總督,想搞清楚他們的身份,所以你需要從真話部落挑一個助手。於是你召開了第X屆全體島民大會,在會上你可以向任何人提問。請問你能不能在不超過4000次提問裏找到一個助手?注意,一次提問是指問一個人,如果你問三個人同樣的問題,算是三次提問,而且任何問題不得涉及1羣人,比如你不能問“這100個人裏最小的真話部落的人是誰”這類問題。

  當時粗略思考了一下,這道題目的條件有個地方很不好把握,即有時說謊的人會不會在總督提問時故意全都說真話來混淆總督。如果真是這樣,別說4000次提問,就是40000次都不一定能找到一個只講真話的助手。而且,整道題目唯一可以確認的條件就是講真話的人比有時說謊的人的數目多。

  爲了求解,只能把有時說謊的人設爲隨機狀態,即有時說謊的人說謊的機率始終保持在1/2附近。Go on then……

  先不考慮4000次提問的條件,我想了一個辦法:每輪先從所有人中隨機挑一個出來,然後向剩下的所有人提問,問本輪選中的人是講真話還是講假話,對答案進行統計。答案相同,人數少的一方肯定全都是有時講假話的人。如果答案相同,人數多的一方回答本輪選中的人講真話,則本輪選中的人必定是講真話的人,助手找到,Bingo!!!否則,篩去本輪選中的人和人數少的一方,剩下的人進入下輪,循環繼續……

  按照這種方法,新任總督最後肯定能找到一個講真話的助手。不過,這個方法花費的提問次數很可能超過4000次。那麼,有沒有優化這個苯算法的方法呢?仔細思考後,我找到了一個入手點,設每輪開始時的總人數是M,提問結束後,答案相同,人數少的一方的人數爲N。則篩完本輪選中的人和人數少的一方後,再從剩下的人中隨機去掉(N+1)人。此時,篩過2次剩下的人中,還是能確保講真話的人數最多。這樣,每輪結束後,提問範圍都可以縮小爲(M-2*N-2)。

  下面算算優化後的有時說謊的人數較多(假設爲最大1002人),且每次選中的人都是有時講真話有時講假話的情況下,能不能滿足最多4000次提問的題設。

  第一輪:2005人中,除開中選者,有時說謊的人數是1001。結果2004次提問中有500人由於講假話被篩,最後一共篩去1002人。取最壞情況,第二次篩去的501人全都講真話;

  第二輪:1003人中,除開中選者,有時說謊的人數是500。結果1002次提問中有250人由於講假話被篩,最後一共篩去502人。取最壞情況,第二次篩去的251人全都講真話;

  第三輪:501人中,除開中選者,有時說謊的人數是249。結果500次提問中有124人由於講假話被篩,最後一共篩去250人。取最壞情況,第二次篩去的125人全都講真話;

  第四輪:251人中,除開中選者,有時說謊的人數是124。結果250次提問中有62人由於講假話被篩,最後一共篩去126人。取最壞情況,第二次篩去的63人全都講真話;

  第五輪:125人中,除開中選者,有時說謊的人數是61。結果124次提問中有30人由於講假話被篩,最後一共篩去62人。取最壞情況,第二次篩去的31人全都講真話;

  第六輪:63人中,除開中選者,有時說謊的人數是30。結果62次提問中有15人由於講假話被篩,最後一共篩去32人。取最壞情況,第二次篩去的16人全都講真話;

  第七輪:31人中,除開中選者,有時說謊的人數是14。結果30次提問中有7人由於講假話被篩,最後一共篩去16人。取最壞情況,第二次篩去的8人全都講真話;

  第八輪:15人中,除開中選者,有時說謊的人數是6。結果14次提問中有3人由於講假話被篩,最後一共篩去8人。取最壞情況,第二次篩去的4人全都講真話;

  第九輪:7人中,除開中選者,有時說謊的人數是2。結果6次提問中有1人由於講假話被篩,最後一共篩去4人。取最壞情況,第二次篩去的2人全都講真話;

  第十輪:最後3人,其中一人有時講真話有時講假話,此時我們共耗去(2004+1002+500+250+124+62+30+14+6)3992次提問機會。最後的8次機會足夠大家找出講真話的助手吧^-^

  
  上述方法在有時說謊的人數較多的情況下可行,那麼是不是意味着在有時講真話有時講假話的人數較少時同樣奏效呢?下面看看2005人中只有11人有時講真話有時講假話的極端情況(同樣的,每次選中的人都是有時講真話有時講假話):

  第一輪:2005人中,除開中選者,有時說謊的人數是10。結果2004次提問中只有5人由於講假話被篩,最後一共篩去12人。取最壞情況,第二次篩去的6人全都講真話;

  第二輪:1993人中,除開中選者,有時說謊的人數是4。結果1992次提問中只有2人由於講假話被篩;

  此時已花去4002次提問,超出題設要求。看來上述方法在這種情況下行不通。且慢,讓我們留意一下每輪由於講假話被刪的人數和提問次數之間的比值先。

  有時說謊的人數是1002人時,2004次提問中有500人露餡,而當這個人數下降到11人時,同樣的2004次提問中只有5人露餡,這就是突破口。我們可以根據這個比值的範圍來確定所有人當中,有時說謊的人數的大致範圍,如果比值在1/4附近,則在保證講真話的人數最多時,雙方人數大致相當。那麼,我們是不是根據這個比值設定一個係數x,讓第二次篩掉(N+1)*x人呢?

  請等一下,讓我們逆轉一下思維先。

  由於先前假設的有時說謊的人說謊的機率始終保持在1/2附近,如果從露餡的人數N入手,可以肯定,隱藏在(M-N-1)的人羣中,有時說謊的人數大致是N。那麼,我們只要從剩下的(M-N-1)的人羣中,隨機抽出(2*N+1)人來。則在這個新抽選的人羣中,一定可以保證講真話的人比有時說謊的人多!!!

  現在我們再看看2005人中只有11人有時說謊的情況下,採用抽選(2*N+1)的辦法有沒有效。

  第一輪:2005人中,除開中選者,有時說謊的人數是10。結果2004次提問中只有5人由於講假話被篩,我們從第一次篩選後的1999人中隨機抽選11人;

  第二輪:11人中,除開中選者,有時說謊的人數最多是4,此時只需10次提問即可。後面就不用分析了。

  而有時說謊的人的人數最多的情況下和上面分析的結果完全相同,最壞情況下在九輪篩選後,花去3992次提問,可得到最終3選2的結果。至此,分析結束。最後總結一下,給出的最終解決方案如下:

  在假定有時說謊的人說謊的機率始終保持在1/2附近的情況下,先從2005人中隨機選1人,向剩下的2004人詢問,選中的人是否有時說謊。如問完2004人後,回答“不是”的人過半,則選中者總是講真話,助手找到。否則,設回答“不是”(即在本輪提問中說謊露餡)的人數爲N,從回答“是”的人羣中隨機抽選出2*N+1人來。重複上面的操作,直至抽選出最後3人,或回答“不是”的人過半。

發佈了37 篇原創文章 · 獲贊 9 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章