遞歸回溯算法解決八皇后問題

問題

image

八皇后問題物臂,是一個古老而著名的問題蛙讥,是回溯算法的典型案例候醒。該問題是國際西洋棋棋手馬克斯·貝瑟爾于1848年提出:在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊哼绑,即:任意兩個皇后都不能處于同一行岩馍、同一列或同一斜線上,問有多少種擺法抖韩。

思路分析

  1. 第一個皇后先放第一行第一列
  2. 第二個皇后放在第二行第一列蛀恩、然后判斷是否OK[即判斷是沖突], 如果不OK茂浮,繼續(xù)放在第二列双谆、第三列、依次把所有列都放完席揽,找到一個合適
  3. 繼續(xù)第三個皇后佃乘,還是第一列、第二列……直到第8個皇后也能放在一個不沖突的位置驹尼,算是找到了一個正確解
  4. 當?shù)玫揭粋€正確解時趣避,在棧回退到上一個棧時新翎,就會開始回溯程帕,即將第一個皇后,放到第一列的所有正確解地啰,全部得到.
  5. 然后回頭繼續(xù)第一個皇后放第二列愁拭,后面繼續(xù)循環(huán)執(zhí)行 1,2,3,4的步驟。

注意點:

說明:理論上應該創(chuàng)建一個二維數(shù)組來表示棋盤亏吝,但是實際上可以通過算法岭埠,用一個一維數(shù)組即可解決問題. arr[8] = {0 , 4, 7, 5, 2, 6, 1, 3} //對應arr 下標 表示第幾行,即第幾個皇后,arr[i] = val , val 表示第i+1個皇后惜论,放在第i+1行的第val+1列许赃。

代碼演示

/**
 * @author 曾鑫曜(xinyao.zeng @ ucarinc.com)
 * @version 1.0
 * @description:
 * @since 2019/9/18 13:31
 */
public class Queue8 {

    //定義一個MAX常量表示一共有多少個皇后
    private static final int MAX = 8;

    //定義一個數(shù)組Array,保存皇后放置的結(jié)果馆类,比如: arr={ 0,4,7,5,2,6,1,3 }  該數(shù)組的下標表示第幾行混聊,具體的值表示第幾列。
    int[] arr = new int[MAX];

    //一共多少種解法
    static int count = 0;

    //一共判斷多少次乾巧,
    static int judgeCount = 0;

    public static void main(String[] args) {

        Queue8 queue8 = new Queue8();
        queue8.check(0);
        System.out.println("八皇后問題解法總數(shù):"+count);
        System.out.println("八皇后問題執(zhí)行次數(shù):"+judgeCount);
    }

    /**
     * 這個方法用于表示放置第N個皇后句喜,依次是第一行表示第一個,第二個表示第二個這樣的思路.
     * 
     * 過程: 
     * 1.如果放置的是最后一個沟于,則直接打印咳胃, 因為只有等于8的時候,表示是都放完了旷太。
     * 否則
     * 1.因為是從第N個開始放拙绊,我們的設計就是從第N行開始計算,遍歷8次泳秀,每次代表放在第N行的第幾列
     * 2.判斷是否沖突标沪,
     * 3.如果沒有沖突繼續(xù)放下一行,直到放到最后一行完成嗜傅。否則會進行回溯
     *
     * @param n
     */
    private void check(int n) {
        //如果為最后一個金句,則打印數(shù)組,同時吕嘀,返回null;
        if(n == MAX){
            print();
            return;
        }
        //否則從第N行的第1個位置開始存放皇后违寞,遍歷存放皇后
        for(int i=0;i<MAX;i++){
            //遍歷存放
            arr[n]=i;
            //判斷與之前是否有沖突。
            if(judge(n)) {
                //如果不沖突偶房,接著N+1趁曼,開始遞歸
               check(n+1);
            }
            //如果沖突,繼續(xù)執(zhí)行array[n]=i,即將第n個皇后放置到本行最后一個位置
        }
    }

    /**
     * 查看我們放置導的第N個皇后棕洋,就去檢測該皇后是否與前面的拜訪沖突
     * @param n 表示第n個皇后
     * @return
     */
    private boolean judge(int n) {

        judgeCount++;
        //n表示與之前的n次對比挡闰,是否有沖突
        for(int i=0; i < n; i++) {
            /**
             * arr[i] == arr[n] 判斷是否有皇后與之前的在同一列
             *
             * Math.abs(n-i) == Math.abs(arr[n] - arr[i])  判斷是否有皇后與之前的皇后在同一斜線上。
             * 判斷依據(jù)取決于我們的設計: 我們設計每一個皇后的位置在數(shù)組的索引表示行掰盘,數(shù)組的所在索引的值表示第幾列摄悯。該方式可以計算是否在同一斜線上。
             *
             * 因為每次檢查必定不會在同一行愧捕,因此不需要檢查同一行的情況奢驯,可以看上面的計算思路
             */
            if(arr[i] == arr[n] || Math.abs(n-i) == Math.abs(arr[n] - arr[i])){
                return false;
            }
        }
        return true;
    }


    //寫一個方法,可以將皇后擺放的位置輸出
    private void print(){
        count++;
        System.out.println(Arrays.toString(arr));
    }
}

計算結(jié)果:

image
image

結(jié)果分析:

  1. 解法總量一共有92種
  2. 執(zhí)行次數(shù)達一萬5千多次效率很低(推薦使用貪心算法改進)
  3. 開上圖圈起部分次绘,看這兩個例子
image

可知瘪阁,如果執(zhí)行到上圖中第一行撒遣,這時候會回到第七行中第五列,繼續(xù)判斷是否有沖突管跺,如果有义黎,則繼續(xù)回到第六行,繼續(xù)遍歷又有沖突伙菜,直到回溯到第四行開始,這是放入第4列命迈,才發(fā)現(xiàn)沒有沖突后贩绕,會繼續(xù)遞歸執(zhí)行。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壶愤,一起剝皮案震驚了整個濱河市淑倾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌征椒,老刑警劉巖娇哆,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異勃救,居然都是意外死亡碍讨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門蒙秒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勃黍,“玉大人,你說我怎么就攤上這事晕讲「不瘢” “怎么了?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵瓢省,是天一觀的道長弄息。 經(jīng)常有香客問我,道長勤婚,這世上最難降的妖魔是什么摹量? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮馒胆,結(jié)果婚禮上荆永,老公的妹妹穿的比我還像新娘。我一直安慰自己国章,他們只是感情好具钥,可當我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著液兽,像睡著了一般骂删。 火紅的嫁衣襯著肌膚如雪掌动。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天宁玫,我揣著相機與錄音粗恢,去河邊找鬼。 笑死欧瘪,一個胖子當著我的面吹牛眷射,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播佛掖,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼妖碉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了芥被?” 一聲冷哼從身側(cè)響起欧宜,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拴魄,沒想到半個月后冗茸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡匹中,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年夏漱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顶捷。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡麻蹋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出焊切,到底是詐尸還是另有隱情扮授,我是刑警寧澤,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布专肪,位于F島的核電站刹勃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嚎尤。R本人自食惡果不足惜荔仁,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芽死。 院中可真熱鬧乏梁,春花似錦、人聲如沸关贵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽揖曾。三九已至落萎,卻和暖如春亥啦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背练链。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工翔脱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人媒鼓。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓届吁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绿鸣。 傳聞我的和親對象是個殘疾皇子疚沐,可洞房花燭夜當晚...
    茶點故事閱讀 45,937評論 2 361

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

  • 什么是八皇后問題 八皇后問題,是一個古老而著名的問題枚驻,是回溯算法的典型案例濒旦。該問題是國際西洋棋棋手馬克斯·貝瑟爾于...
    呀哎_cee6閱讀 276評論 0 0
  • 回溯算法 回溯法:也稱為試探法株旷,它并不考慮問題規(guī)模的大小再登,而是從問題的最明顯的最小規(guī)模開始逐步求解出可能的答案,并...
    fredal閱讀 13,675評論 0 89
  • 1.八皇后問題介紹 八皇后問題晾剖,是一個古老而著名的問題锉矢,是回溯算法的典型案例。該問題是國際西洋棋棋手馬克斯·貝瑟爾...
    21號新秀_鄧肯閱讀 382評論 0 3
  • 學習原因:解決this的指向問題 1. apply()函數(shù)和call()函數(shù)-有兩個參數(shù)(this,array)a...
    小鋒子_Gruad閱讀 131評論 0 0
  • 每次談起畢業(yè)初在外地的租房經(jīng)歷齿尽,陶樂樂都會提起弗朗西斯筆下的那個小公主沽损。 陶樂樂的房子活了。 確切地說是房里的家居...
    DISS諦獅閱讀 79評論 0 0