C 解決類似愛因斯坦測試題的問題V2 0

2021-06-26 14:16:20 字數 4266 閱讀 8314

原來的部落格是去年大二的時候寫的,後來發現沒有解釋可能比較難看懂(畢竟**比較長),於是後面加了一段解說,但是發現以前的部落格摘要居然沒有改過來。。。。於是一直想著要重新寫一篇,直到最近老師布置相關作業,我順手把這個演算法優化了一下,去掉了一些多於的操作和不合理的結構,演算法的時間消耗頓時減少了一半多(優化很重要啊)!

下面進入正題:

首先是題目(非愛因斯坦測試原題,不知道是哪個老師出的╮(╯▽╰)╭):

有五座房子,每座房子的顏色不同,裡面分別住著不同國家的人,每個人都有自己養的不同寵物喜歡喝的不同飲料、抽的不同牌子的煙。現已知以下一些資訊:

英國人住在紅色的房子裡 ;

西班牙人養了一條狗;

挪威人住在左邊的第乙個房子裡;

黃房子裡的人喜歡抽kools牌的香菸;

抽chesterfields牌香菸的人與養狐狸的人是鄰居;

挪威人住在藍色房子旁邊;

抽winston牌香菸的人養了乙個蝸牛;

抽lucky strike牌香菸的人喜歡喝橘子汁;

烏克蘭人喜歡喝茶;

日本人抽parlianments牌的煙;

抽kools牌香菸的人與養馬的人是鄰居;

喜歡喝咖啡的人住在綠房子裡;

綠房子在象牙白房子的右邊;

中間那個房子裡的人喜歡喝牛奶。

根據以上條件,請你判斷哪個房子裡的人養斑馬?哪個房子裡的人喜歡喝水?最後把所有的東西對號入座。

**太長,就不先上了。先看執行結果:

首先說一下,由於不能確定答案的個數,所以遍歷所有的情況是必須的,也就是說即使找出了乙個答案,程式也不能立即返回,因為答案有可能不唯一。

然後是解題思路,剛開始也沒什麼思路,經過一番混沌式的探索之後(……),漸漸摸到一些門道。核心思想就是"分層過濾"。將房子從左到右(或者從右到左也可以)依次搭建起來,如果建立的房子滿足條件,則保留並建立下一所房子,否則推倒重建。這樣可以減少大量不必要的計算組合,速度也會快很多。

說到過濾,過濾的條件自然是重要的。

根據題目提供的資訊,我們可以將所給的14個條件分為三類:

然後,根據前面說過的方法,這裡選擇從左往右進行搭建,生成物件時,如果有確定型的關係,則直接運用到屬性中,其他條件則使用迴圈進行遍歷。物件生成之後,放入條件表示式中進行匹配,如果滿足條件,就以此為基礎生成下乙個物件,否則就打回重建。

大致原理就是這樣,關鍵點在於條件怎麼組合才能最大限度的將所有不符合條件的物件駁回,以減少後續篩選判斷的次數。

簡而言之,利用原命題與逆否命題的等價性,我們可以對判斷條件的邏輯進行強化,以達到增強篩選條件的目的。

舉個例子:"英國人住在紅色的房子裡"這個條件,如果直接翻譯就是"如果乙個物件的國籍是英國,並且他所住的房子是紅色的,則條件為真";而他的逆否命題「不住在紅色房子裡的人不是英國人」這樣一句看起來很繞,聽起來像廢話一樣的句子翻譯後的效果就不一樣了,它的翻譯是「如果存在乙個物件的國籍是英國,並且他住的房子不是紅色 或者 如果存在乙個物件的房子是紅色,但是他的國籍不是英國,則條件為假」。這個條件很顯然比前面乙個條件能篩掉的組合更多。要知道,漏篩一種情況對後面的條件判斷次數的影響都是巨大的,所以,越先建立的物件要篩得的越徹底越好。對比下面乙個圖,你可以看到區別。

下圖是加入了五個經過人工分析後得到的條件的運算結果,這五個條件分別是:

第一間房子不是紅色、藍色、白色,主人不喝牛奶、茶,不抽parlianments煙,不養狗

第二間房子不住挪威人、英國人,主人不喝咖啡、牛奶,不抽kools的煙

第三間房自不是綠色、藍色,主人不是烏克蘭人,不是挪威人,不抽lucky strike的煙

第四間房子不是藍色、紅色、黃色,主人不是挪威人,不喝牛奶

第五間房子不是藍色、白色,主人不是挪威人,不喝牛奶

其中t1,t2,t3,t4,t5分別是每棟房子通過篩選條件的次數,從中我們可以計算出上圖的結果是經過 13×78×65×141×141 >13億次遍歷建立的,而下面的結果只經歷了1×3×11×17×11=6171次遍歷,差異明顯。

下面是本程式的全部**(為了**的可讀性,大部分列舉常量採用中文定義):

//有五座房子,每座房子的顏色不同,裡面分別住著不同國家的人,每個人都有自己養的不同寵物、

//英國人住在紅色的房子裡;

//西班牙人養了一條狗;

//挪威人住在左邊的第乙個房子裡;

//黃房子裡的人喜歡抽kools牌的香菸;

//抽chesterfields牌香菸的人與養狐狸的人是鄰居;

//挪威人住在藍色房子旁邊;

//抽winston牌香菸的人養了乙個蝸牛;

//抽lucky strike牌香菸的人喜歡喝橘子汁;

//烏克蘭人喜歡喝茶;

//日本人抽parlianments牌的煙;

//抽kools牌香菸的人與養馬的人是鄰居;

//喜歡喝咖啡的人住在綠房子裡;

//綠房子在象牙白房子的右邊;

//中間那個房子裡的人喜歡喝牛奶。

//根據以上條件,請你判斷哪個房子裡的人養斑馬?哪個房子裡的人喜歡喝水?最後把所有的東西對號入座。

using system;

using system.diagnostics;

namespace 愛因斯坦智力題暴力破解

ms", ts.elapsedmilliseconds);

console.readkey(true);}}

public class work

public bool start()

//組裝第一間房子(從左往右數)

private bool h1()

}return false;

}//組裝第二間房子

private bool h2()

}progress--;

return false;

}//組裝第三間房子

private bool h3()

}progress--;

return false;

}//組裝第四間房子

private bool h4()

}progress--;

return false;

}//組裝第五間房子

private bool h5()

}progress--;

return false;

}private bool match() //二維條件的逆否式

private bool test()

return false;

}private bool test_1()//已給定的二維條件4/8

private bool test_2()//已給定的二維條件4/8

private bool test_3()//相鄰位置判斷條件3/3

public void showresult()

\nt2:\nt3:\nt4:\nt5:\n", t1, t2, t3, t4, t5);

}public void anwser()

人喝", persons[i].country, persons[i].drink);

for (int i = 1; i <= 5; i++)

if (persons[i].pet == pet.斑馬)

console.writeline(" 人養", persons[i].country, persons[i].pet);

console.writeline();}}

public enum housecolor

public enum country

public enum pet

public enum drink

public enum smoke

public class person

public person(int h, int c, int p, int d, int s)

switch (c)

switch (p)

switch (d)

switch (s)

}public bool hasequal(person pe)//只要有部分元素相等則返回真,非全等

public override string tostring()}}

C語言 愛因斯坦的階梯問題

愛因斯坦曾經提出過這樣一道有趣的數學題 有乙個長階梯,若每步上2階,最後剩下1階 若每步上3階,最後剩2階 若每步上5階,最後剩下4階 若每步上6階,最後剩5階 只有每步上7階,最後剛好一階也不剩。請問該階梯至少有多少階 int i 7 int times 1000 while i 2 1 i 3 ...

有趣的C語言測試題

1.gets 函式 問 請找出下面 裡的問題 include int main void 2.strcpy 函式 問 下面是乙個簡單的密碼保護功能,你能在不知道密碼的情況下將其破解嗎?include int main int argc,char argv if flag else return 0 ...

C語言幾個精典的測試題

最近學習c語言,發現有幾個測試題是最容易錯的,不知道學習c語言的朋友也會犯這樣的錯誤呢?1.大家看以下 會輸出什麼 void main a a b 100 c c d d 我們知道宣告了乙個字元型變數,同時給它初始化為ch a 3 那麼這裡就應該輸出 d 我們知道字元型變數在記憶體中是以整型儲存的,...