關(guān)于八皇后問題以及回溯遞歸思想

大家好,我是“Stephen·謝”第练,本文以古老的八皇后問題的文字解釋和代碼實(shí)現(xiàn),將遞歸回溯的思想概念介紹給大家呕寝。


國際象棋中的皇后比中國象棋里的大車還厲害下梢,皇后能橫向,縱向和斜向移動(dòng)讶坯,在這三條線上的其他棋子都可以被吃掉岗屏。所謂八皇后問題就是:將八位皇后放在一張8x8的棋盤上这刷,使得每位皇后都無法吃掉別的皇后,(即任意兩個(gè)皇后都不在同一條橫線似袁,豎線和斜線上),問一共有多少種擺法扬霜。此問題是在1848年由棋手馬克思·貝瑟爾提出的而涉,后面陸續(xù)有包括高斯等大數(shù)學(xué)家們給出自己的思考和解法婴谱,所以此問題不只是有年頭了,簡直比82年的拉菲還有年頭华糖,我們今天不妨嘗嘗這老酒瘟裸。

我們先舉例來理解一下這個(gè)問題的場景到底是什么樣子的话告,下面的綠色格子是一個(gè)皇后在棋盤上的“封鎖范圍”,其他的皇后不能放置在這些綠格子中:

一個(gè)皇后的封鎖范圍

我們再放入一個(gè)皇后佛呻,看一下兩個(gè)皇后的“封鎖范圍”(綠格子不能放):

兩個(gè)皇后的封鎖范圍

如此繼續(xù)下去吓著,能安放下一位皇后的位置越來越少绑莺,那么我們最終如何能安放完這8位皇后呢惕耕?

首先我們看一下特別暴力的方法:從8x8的格子里選8個(gè)格子司澎,放皇后,然后測試是否滿足條件浪南,若滿足則結(jié)果加1漱受,否則換8個(gè)格子繼續(xù)試。很顯然絮记,64選8怨愤,并不是個(gè)小數(shù)字,十億級(jí)別的次數(shù)篮愉,夠暴力差导。如果換成圍棋的棋盤设褐,畫面就會(huì)太美而不敢算。

稍加分析犀被,我們可以得到另一個(gè)不那么暴力的方法:顯然寡键,每行每列最多只能有一位皇后雪隧,如果基于這個(gè)事實(shí)再進(jìn)行暴力破解,那結(jié)果會(huì)好很多膀跌。安排皇后時(shí),第一行有8種選法固灵,一旦第一行選定捅伤,假設(shè)選為(1,i)巫玻,那么第二行只能選(2丛忆,j),其中仍秤,j不等于i熄诡,所以有7種選法。以此類推诗力,需要窮舉的情況有8!=40320種,比十億級(jí)別的小很多了袜茧。

這看起來已經(jīng)不錯(cuò)了菜拓,但嘗試的次數(shù)還是隨著問題規(guī)模按階乘水平提高的,我們?nèi)匀徊粷M意笛厦,所以纳鼎,“遞歸回溯”的思想就被提出了,專治這種問題裳凸。

為了理解“遞歸回溯”的思想贱鄙,我們不妨先將4位皇后打入冷宮,留下剩下的4位安排進(jìn)4x4的格子中且不能互相打架姨谷,有多少種安排方法呢逗宁?如果按照上面方式窮舉,需要4菠秒!=24次嘗試嗎疙剑?

現(xiàn)在我們把第一個(gè)皇后放在第一個(gè)格子,被涂黑的地方是不能放皇后的:

放第1個(gè)皇后

第二行的皇后只能放在第三格或第四格践叠,比如我們放在第三格:

放第2個(gè)皇后

這樣一來前面兩位皇后已經(jīng)把第三行全部鎖死了言缤,第三位皇后無論放在第三行的哪里都難逃被吃掉的厄運(yùn)。于是在第一個(gè)皇后位于第一格禁灼,第二個(gè)皇后位于第三格的情況下此問題無解管挟。所以我們只能返回上一步,來給2號(hào)皇后換個(gè)位置:

給2號(hào)皇后換個(gè)位置

此時(shí)弄捕,第三個(gè)皇后只有一個(gè)位置可選僻孝。當(dāng)?shù)谌齻€(gè)皇后占據(jù)第三行藍(lán)色空位時(shí),第四行皇后無路可走守谓,于是發(fā)生錯(cuò)誤穿铆,則返回上層調(diào)整3號(hào)皇后,而3號(hào)皇后也別無可去斋荞,繼續(xù)返回上層調(diào)整2號(hào)皇后荞雏,而2號(hào)皇后已然無路可去,則再繼續(xù)返回上層調(diào)整1號(hào)皇后平酿,于是1號(hào)皇后往后移一格位置如下凤优,再繼續(xù)往下安排:

回溯重新安排1號(hào)皇后

上面的圖例正是回溯遞歸思想的展現(xiàn),然而知易行難蜈彼,在代碼中我們怎樣來實(shí)現(xiàn)這種算法呢筑辨?實(shí)現(xiàn)的代碼有很多種,我們找一個(gè)最簡單的來舉例吧:

遞歸回溯的核心代碼

我們來重點(diǎn)看一下這段代碼(這段代碼雖短幸逆,但真的非常非常重要棍辕,是整個(gè)算法的核心和靈魂):

第一次進(jìn)來暮现,row=0,意思是要在第一行擺皇后痢毒,只要傳進(jìn)來的row參數(shù)不是8送矩,表明還沒出結(jié)果,就都不會(huì)走if里面的return哪替,那么就進(jìn)入到for循環(huán)里面栋荸,column從0開始,即第一列凭舶。此時(shí)第一行第一列肯定合乎要求(即check方法肯定通過)晌块,能放下皇后,因?yàn)檫€沒有任何其他皇后來干擾帅霜。

關(guān)鍵是check方法通過了之后匆背,在if里面又會(huì)調(diào)用一下自己(即遞歸),row加了1身冀,表示擺第二行的皇后了钝尸。第二行的皇后在走for循環(huán)的時(shí)候,分兩種情況搂根,第一種情況:for循環(huán)沒走到頭時(shí)就有通過check方法的了珍促,那么這樣就順理成章地往下走再調(diào)用一下自己(即再往下遞歸),row再加1(即擺第三行的皇后了剩愧,以此類推)猪叙。第二種情況:for循環(huán)走到頭了都沒有通過check方法的,說明第二行根本一個(gè)皇后都擺不了仁卷,也觸發(fā)不了遞歸穴翩,下面的第三行等等后面的就更不用提了,此時(shí)控制第一行皇后位置的for循環(huán)column加1锦积,即第一行的皇后往后移一格芒帕,即擺在第一行第二列的位置上,然后再往下走丰介,重復(fù)上述邏輯背蟆。

注意,一定要添加清零的代碼基矮,它只有在皇后擺不下去的時(shí)候會(huì)執(zhí)行清0的動(dòng)作(避免臟數(shù)據(jù)干擾)淆储,如果皇后擺放很順利的話從頭到尾是不會(huì)走這個(gè)請0的動(dòng)作的冠场,因?yàn)橐呀?jīng)提前走if里面的return方法結(jié)束了家浇。

總之,這段核心代碼很繞碴裙,原理一定要想通钢悲,想個(gè)十幾二十遍差不多就能理解其中的原理了点额,遞歸回溯的思想也就不言而喻了。八皇后問題一共有92種情況莺琳,下面是用Java實(shí)現(xiàn)的完整代碼:

public static int[][] arry=new int[8][8];//棋盤还棱,放皇后
public static int map=0;//存儲(chǔ)方案結(jié)果數(shù)量

public static void main(String[] args) {
    // TODO Auto-generated method stub

    System.out.println("八皇后問題");
    findQueen(0);
    System.out.println("八皇后問題共有:"+map+"種可能");
}

public static void findQueen(int i){//尋找皇后節(jié)點(diǎn)
    if(i>7){//八皇后的解  
        map++;
        print();//打印八皇后的解
        return;
    }
    
    for(int m=0;m<8;m++){//深度回溯,遞歸算法
        if(check(i,m)){//檢查皇后擺放是否合適
            arry[i][m]=1;
            findQueen(i+1);
            arry[i][m]=0;//清零,以免回溯的時(shí)候出現(xiàn)臟數(shù)據(jù)
            }
    }   
}

public static boolean check(int k,int j){//判斷節(jié)點(diǎn)是否合適
    for(int i=0;i<8;i++){//檢查行列沖突
         if(arry[i][j]==1){
                return false;
         }
    }
    for(int i=k-1,m=j-1; i>=0 && m>=0; i--,m--){//檢查左對(duì)角線
        if(arry[i][m]==1){
                return false;
        }
    }
    for(int i=k-1,m=j+1; i>=0 && m<=7; i--,m++){//檢查右對(duì)角線
        if(arry[i][m]==1){
                return false;
        }
    }
    return true;
}

public static void print(){//打印結(jié)果
    System.out.print("方案"+map+":"+"\n");
    for(int i=0;i<8;i++){
        for(int m=0;m<8;m++){
            if(arry[i][m]==1){  
                //System.out.print("皇后"+(i+1)+"在第"+i+"行惭等,第"+m+"列\(zhòng)t");
                System.out.print("o ");
            }
            else{
                    System.out.print("+ ");
            }
        }
        System.out.println();
    }
    System.out.println();
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末珍手,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子辞做,更是在濱河造成了極大的恐慌琳要,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秤茅,死亡現(xiàn)場離奇詭異稚补,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)框喳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門课幕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人五垮,你說我怎么就攤上這事乍惊。” “怎么了拼余?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵污桦,是天一觀的道長。 經(jīng)常有香客問我匙监,道長凡橱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任亭姥,我火速辦了婚禮稼钩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘达罗。我一直安慰自己坝撑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布粮揉。 她就那樣靜靜地躺著巡李,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扶认。 梳的紋絲不亂的頭發(fā)上侨拦,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音辐宾,去河邊找鬼狱从。 笑死膨蛮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的季研。 我是一名探鬼主播敞葛,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼与涡!你這毒婦竟也來了惹谐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤驼卖,失蹤者是張志新(化名)和其女友劉穎豺鼻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體款慨,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡儒飒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了檩奠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桩了。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖埠戳,靈堂內(nèi)的尸體忽然破棺而出井誉,到底是詐尸還是另有隱情,我是刑警寧澤整胃,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布颗圣,位于F島的核電站,受9級(jí)特大地震影響屁使,放射性物質(zhì)發(fā)生泄漏在岂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一蛮寂、第九天 我趴在偏房一處隱蔽的房頂上張望蔽午。 院中可真熱鬧,春花似錦酬蹋、人聲如沸及老。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽骄恶。三九已至,卻和暖如春匕垫,著一層夾襖步出監(jiān)牢的瞬間僧鲁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悔捶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓单芜,卻偏偏與公主長得像蜕该,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洲鸠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 回溯算法 回溯法:也稱為試探法堂淡,它并不考慮問題規(guī)模的大小,而是從問題的最明顯的最小規(guī)模開始逐步求解出可能的答案扒腕,并...
    fredal閱讀 13,626評(píng)論 0 89
  • 什么是八皇后問題? 八皇后問題是一個(gè)古老的問題绢淀,于1848年由一位國際象棋棋手提出:在8×8格的國際象棋上擺放八個(gè)...
    Soujiro閱讀 2,033評(píng)論 0 3
  • 八皇后問題是一個(gè)經(jīng)典的遞歸回溯問題。 描述 八皇后問題是在一個(gè) 8*8 的棋盤上放置皇后瘾腰,要求其放置后滿足同一行皆的,...
    JYGod丶閱讀 2,339評(píng)論 1 3
  • 八皇后問題問題描述:八皇后問題费薄,是一個(gè)古老而著名的問題,是回溯算法的典型案例栖雾。該問題是國際西洋棋棋手馬克斯·貝瑟爾...
    藥藥耀耀閱讀 2,067評(píng)論 0 0
  • 【旅行雪鄉(xiāng)故事】雪龍峰其實(shí)就是大禿頂子山的最高峰析藕,海拔1691米召廷,從大雪谷門前徒步到雪龍峰頂10公里左右,純玩的游...
    勒克兒閱讀 507評(píng)論 1 3