国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

用窮舉法解愛(ài)因斯坦問(wèn)題

2018-02-28 11:25:32李振夏
電子技術(shù)與軟件工程 2018年13期
關(guān)鍵詞:長(zhǎng)郡中學(xué)排列組合愛(ài)因斯坦

李振夏

摘要 上個(gè)世紀(jì),大科學(xué)家愛(ài)因斯坦提出了一道非常經(jīng)典的邏輯題“誰(shuí)在養(yǎng)魚”?這是一道很非常經(jīng)典的智力題,據(jù)愛(ài)因斯坦說(shuō),全世界只有大約2%的聰明人,能夠推得出這個(gè)問(wèn)題的答案。在沒(méi)有計(jì)算機(jī)的年代,相信普通人看到這個(gè)問(wèn)題無(wú)從下手,聰明者基本都是以表格的方式來(lái)推導(dǎo)。計(jì)算機(jī)出現(xiàn)后很多依靠人腦無(wú)法完成的事情可以變得順利成章了。本文要介紹的方法就是這樣:以窮舉法來(lái)破解這道題。

【關(guān)鍵詞】愛(ài)因斯坦 窮舉法 Java編程 排列組合 長(zhǎng)郡中學(xué)

1 問(wèn)題描述

上個(gè)世紀(jì),大科學(xué)家愛(ài)因斯坦提出了一道非常經(jīng)典的邏輯題,題目的內(nèi)容是這樣的:在一條街上有五個(gè)不同顏色的房間排成一排,每個(gè)房間里分別住著一個(gè)不同國(guó)籍的人,每個(gè)人都喝一種特定品牌的飲料,抽一種特定品牌的煙,養(yǎng)一種寵物,沒(méi)有任意兩個(gè)人抽相同品牌的香煙,或喝相同品牌的飲料,或養(yǎng)相同的寵物,又知:

(1)英國(guó)人住在紅房子里。

(2)瑞典人養(yǎng)狗。

(3)丹麥人喝茶。

(4)綠房子緊挨著白房子,在白房子的左邊。

(5)綠房子的主人喝咖啡。

(6)抽PALL MALL牌香煙的人養(yǎng)鳥。

(7)黃房子里的人抽DUNHILL牌的煙。

(8)住中間房子的人喝牛奶。

(9)挪威人住在第一個(gè)房子里(最左邊)。

(10)抽BLENDS香煙的人和養(yǎng)貓的人相鄰。

(11)養(yǎng)馬的人和抽DUNHILL牌香煙的人相鄰。

(12)抽BLUEMASTER牌香煙的人喝啤酒。

(13)德國(guó)人抽PRINCE牌香煙。

(14)挪威人和住藍(lán)房子的人相鄰。

(15)抽BLENDS牌香煙和喝礦泉水的人相鄰。

問(wèn)題:誰(shuí)在養(yǎng)魚?

2 解題思路

就這道題來(lái)說(shuō),窮舉法是最直接也是容易讓人理解的方法。所謂窮舉法的基本思想是根據(jù)題目的部分條件確定答案的大致范圍,并在此范圍內(nèi)對(duì)所有可能的情況逐一驗(yàn)證,直到全部情況驗(yàn)證完畢。若某個(gè)情況驗(yàn)證符合題目的全部條件,則為本問(wèn)題的一個(gè)解;若全部情況驗(yàn)證后都不符合題目的全部條件,則本題無(wú)解。就本道題而言肯定就只有一個(gè)答案。

在正式計(jì)算之前,需要先來(lái)討論一下答案的形式和范圍。就這套題而言,有五個(gè)房子(在面向?qū)ο蟮某绦蛑蟹Q為實(shí)體),每個(gè)房子從左到右依次排列,每個(gè)房子有個(gè)序號(hào)分別從O到4(在這里就按照程序的思維來(lái)進(jìn)行,從O開始進(jìn)行編號(hào)),每個(gè)房子分別有五個(gè)屬性:房屋的顏色(以下簡(jiǎn)稱顏色)、居住者的國(guó)籍(以下簡(jiǎn)稱國(guó)籍)、居住者的喜愛(ài)的飲料(以下簡(jiǎn)稱飲料)、居住者喜歡的香煙(以下簡(jiǎn)稱香煙)、居住者養(yǎng)的寵物(以下簡(jiǎn)稱寵物)。這五個(gè)屬性每種屬性有5個(gè)值,那么一共有多少個(gè)可能的解呢?為了弄清這個(gè)問(wèn)題,讓我們先從一個(gè)屬性來(lái)分析,假設(shè)單單就顏色來(lái)說(shuō),總共5中顏色,分給5套房子,有多少中可能性呢?在學(xué)了數(shù)學(xué)的排列定理后,我們知道這里其實(shí)就是一個(gè)排列組合問(wèn)題:

就顏色的來(lái)說(shuō),實(shí)際上就是5的全排列。可能的組合數(shù)為:5*4*3*2*1=120種排列方式。知道了就一種屬性來(lái)說(shuō)有120種可能性,那么就5個(gè)屬性來(lái)說(shuō),他們的可能組合數(shù)為120*120*120*120*120= 24883200000個(gè)可能的解(這么龐大的數(shù)字,如果不做優(yōu)化就人來(lái)說(shuō)幾乎就是不可能完成的)。

了解了解題思路后,接下來(lái)要做的就是分別對(duì)顏色、國(guó)籍、飲料、香煙和寵物計(jì)算出每個(gè)屬性的所有可能的排列組合并將這些組合放到5個(gè)數(shù)組里面,然后再用多層循環(huán)的方式,從每個(gè)數(shù)組中取出一個(gè)組合進(jìn)行校驗(yàn):其實(shí)簡(jiǎn)單,具體如何校驗(yàn)?zāi)??題中的15調(diào)線索,每條就是一個(gè)校驗(yàn)規(guī)則。

3 解題算法

3.1 數(shù)據(jù)初始化

聲明5各列表,每個(gè)列表中依次放入相關(guān)的選項(xiàng)

private static List nationalities;

private static List houseColors;

private static List drinks;

private sratic List smokings;

private sratic List pets;

static{

//初始化數(shù)據(jù)

nationalities= Arrays.asList(“英國(guó)”,“瑞典”,“丹麥”,“挪威”,“德國(guó)”);

houseColors= Arrays.asList(“紅”,“綠”,“白”,“黃”,“藍(lán)”);

drinks= Arrays.asList(“茶”,“咖啡”,“牛奶”,“啤酒”,“礦泉水”);

smokings= Arrays.asList("PALLMALL", "DUNHILL", "BLENDS",”BLUEMASTER", "PRINCE");

pets= Arrays.asList(“狗”,“鳥”,“馬”,“貓”,“魚”);

3.2 排列組合的計(jì)算

就本題而言,一個(gè)最為核心和重要的就是如何算出一組數(shù)據(jù)的排列組合。設(shè)a、b、c、d、e五個(gè)數(shù)為一組,如何算出這5個(gè)組的所有排列組合的形式。根據(jù)假設(shè)對(duì)一個(gè)有n位的數(shù)組來(lái)說(shuō),第一位有n種選擇,第2位有n.1種選擇,第一位和第二位的組合有n*(n-l)各,他們與3位的組合有n*(n-1)*(n-2)個(gè)。依次進(jìn)行遞歸前面n-l位與最后一位的組合只剩下一種形式,依次得出算法如下:

/{{

*求list中元素的所有排列組合

* @param list列表中的元素

* @return

*/

public static List list){

List

List line=newArrayList();

permutarion(line, lisr, result);

return result,

/**

*計(jì)算所有的排列組合

* @param line前面元素的組合

* @param remains剩余還沒(méi)有組合的元素

* @param result保存最終的計(jì)算結(jié)果,里面的每個(gè)list是一種組合形式

*/

private static void permutation(Listline, List remains, List

line= cloneList(line);

remains= cloneList(remains);

int size= remains.size(),

if (size==1){∥如果只有一個(gè)元素,那么就只有直接用前面的組合跟這個(gè)元素進(jìn)行拼合

line.add(remains.get(0》;

result.add(line);

return,

for (inti=0;i

String one= remains.get(i);//取出某一個(gè)元素

Lisr remains2=without(remains, one);//剔除該元素的列表

permutation(one, cloneList(line),remains2, result);

*計(jì)算出某一個(gè)元素與前面組合的拼合結(jié)果

* @param one某個(gè)元素(下一個(gè)加入的元素)

* @param line需要加入的隊(duì)列(某個(gè)組合)

* @param remains2剩余的元素

* @param result存儲(chǔ)最終的結(jié)果

*/,

private static void permutation(Stringone, List Iine, List remains2,List

line= cloneList(line);

line.add(one);

permutation(line, remains2, result);

3.3 規(guī)則檢驗(yàn)

有了上一小節(jié)的排列算法,我們可以每次先對(duì)房屋(或房屋主人的)國(guó)籍、顏色、飲料、香煙、寵物算出所有的排列組合,然后循環(huán)這些組合,每次針對(duì)這五個(gè)屬性各拿出一個(gè)組合進(jìn)行校驗(yàn)。題中的15條線索就是15個(gè)校驗(yàn)規(guī)則,我們需要針對(duì)每個(gè)規(guī)則完成一個(gè)檢查方法,某一組合符合所有的規(guī)則,那么就是正解。以第一個(gè)規(guī)則為例方法如下:

*檢查條件:英國(guó)人住在紅房子里。

* @param nationList國(guó)籍列表

* @param colorList房屋顏色

* @retum檢查通過(guò)返回true,否則返回false

private static boolean checkEnglishInRedHouse(List nationList, ListcolorList){

int index= nationList.indexOf(“英國(guó)”);∥獲得英國(guó)人做在的房屋序號(hào)

String color= colorList.get(index);//獲得同一序號(hào)的房屋顏色

retum紅”equals(color);

3.4 窮舉算法

在以上的算法的基礎(chǔ),最終的窮舉算法如下:

public static void main(String[] args){

List

List

List

List

List

index=O:

long beginTime=System.currentTimeMillis();

int size= nationPermutations.size();//

//以下針對(duì)每個(gè)屬性循環(huán),檢驗(yàn)每個(gè)解

for (intn=O;n

List nationList=nationPermutations.get(n);

for (int c=O;c

List colorLisr=colorPermutations.get(c);

for (int d=O;d

List drinkList=drinkPermutations.get(d);

for (inr s=O;s

List smokeList=smokePermutations.get(s);

for (intp=0;p

Lisr petList=petPermutations.get(p);

index++;

if (checkPass(narionLisr,colorList, drinkList, smokeList, petList》{

//檢驗(yàn)通過(guò)

System.out.println("計(jì)算用時(shí):”+ (System.currentTimeMillis() -beginTime)+“毫秒”);

printResult(nationList,colorList, drinkList, smokeList, petList);

retum,

) else{

//System.outprintln("error at”+index);

}

}

System.out.println(”程序運(yùn)行結(jié)束!”);

3.5 算法優(yōu)化

在上一小節(jié)中,依次用了5層循環(huán)來(lái)對(duì)檢驗(yàn)每個(gè)解,前面說(shuō)過(guò)這樣的解一共有24883200000個(gè)。這樣的數(shù)量對(duì)于計(jì)算機(jī)來(lái)說(shuō)運(yùn)算次數(shù)也還是非常大的。為了最大幅度的減少運(yùn)算次數(shù),可以在外層循環(huán)中就逐步加入一些校驗(yàn)規(guī)則,篩選掉一些無(wú)用的解。大致如下:

for (intn=0;n

List nationLisr=nationPermutations.get(n);

if(! checkFirstHouseIsNorwegian(nationList》{//檢查第一間房是否是挪威人,這個(gè)只跟nationList有關(guān)系

continue,

}

for (int c=0;c

Lisr colorList=colorPermutations.get(c);

if (!checkGreenLeftOfWhite(colorList》{∥檢查綠色房子是否在白色房子的左邊

contmue,

}

if( !checkEnglishInRedHouse(nationList, colorList》{//檢查英國(guó)人是否住紅色房子

contmue,

}

if(! checkNearbyNorwegianWirhBlueHouse(nationList, colorList》{∥挪威人和住藍(lán)房子的人相鄰

contmue,

for (int d = 0;d

提前加入校驗(yàn)的原則就是,在某一層循環(huán)加入的校驗(yàn)算法只與前面幾層的屬性相關(guān),這樣校驗(yàn)方法才能正常執(zhí)行。

3.6 計(jì)算結(jié)果

4 總結(jié)

采用窮舉法來(lái)解題的最直接的優(yōu)點(diǎn)就是直觀、便于理解。從缺點(diǎn)方面來(lái)說(shuō),窮舉法最大的缺點(diǎn)就是通常計(jì)算量都很大,但本處解題由于對(duì)程序進(jìn)行了優(yōu)化,提早加入校驗(yàn)方法,已經(jīng)讓計(jì)算量大幅的降低,運(yùn)算效率大大提高。(程序查看和下載地址:https://giteecom/lizhenxia/einstein).

參考文獻(xiàn)

[1]張傳鵬.高考數(shù)學(xué)進(jìn)階特訓(xùn)[M]。浙江:浙江大學(xué)出版社,2016.

[2]白喜琇(韓).狄利克雷教你學(xué)選擇和排列[M].安徽:黃山書社出版,2016.

[3]明日科技.Java從入門到精通(第4版)[M].北京:清華大學(xué)出版社,2016.

[4]宋娟.Java常用算法手冊(cè)(第3版)[M].北京:中國(guó)鐵道出版社,2016.

[5] Robert Sedgewick(美),KevlnWayne(美)著;謝路云譯,算法第4版Algorithms Fourth Edition[M].北京:人民郵電出版社,2012.

猜你喜歡
長(zhǎng)郡中學(xué)排列組合愛(ài)因斯坦
為什么愛(ài)因斯坦總是“爆炸頭”
活用數(shù)學(xué)模型,理解排列組合
史上最全的排列組合22種解題策略
愛(ài)因斯坦的夢(mèng)
文苑(2020年4期)2020-05-30 12:35:14
校園開場(chǎng)show
十幾歲(2017年3期)2017-07-05 14:45:34
我不是懷念中學(xué)
十幾歲(2017年5期)2017-06-21 15:10:08
離開地表 瞰長(zhǎng)沙
十幾歲(2017年4期)2017-05-03 01:20:57
叮鈴鈴,上課啦!
十幾歲(2017年4期)2017-05-03 01:03:25
勤奮努力的愛(ài)因斯坦
小議排列組合問(wèn)題常用解法
考試周刊(2017年4期)2017-01-19 15:57:09
仁寿县| 乐昌市| 象州县| 泽库县| 定结县| 九江县| 铜山县| 巴南区| 宿松县| 武安市| 常州市| 龙陵县| 岢岚县| 安徽省| 宜宾县| 通州区| 西青区| 科技| 温州市| 交城县| 平利县| 南宁市| 新安县| 抚顺市| 囊谦县| 贵德县| 韩城市| 芒康县| 南陵县| 宝鸡市| 化德县| 江西省| 邵阳县| 乌恰县| 通河县| 石棉县| 新昌县| 廉江市| 南川市| 普宁市| 繁昌县|