回溯法解八皇后問(wèn)題

問(wèn)題介紹

摘自百度百科
八皇后問(wèn)題,是一個(gè)古老而著名的問(wèn)題,是回溯算法的典型案例。該問(wèn)題是國(guó)際西洋棋棋手馬克斯·貝瑟爾于1848年提出:在8×8格的國(guó)際象棋上擺放八個(gè)皇后,使其不能互相攻擊部服,即任意兩個(gè)皇后都不能處于同一行、同一列或同一斜線上拗慨,問(wèn)有多少種擺法廓八?

回溯法

概念

摘自百度百科
回溯法(探索與回溯法)是一種選優(yōu)搜索法,又稱為試探法赵抢,按選優(yōu)條件向前搜索剧蹂,以達(dá)到目標(biāo)。但當(dāng)探索到某一步時(shí)烦却,發(fā)現(xiàn)原先選擇并不優(yōu)或達(dá)不到目標(biāo)宠叼,就退回一步重新選擇,這種走不通就退回再走的技術(shù)為回溯法,而滿足回溯條件的某個(gè)狀態(tài)的點(diǎn)稱為“回溯點(diǎn)”冒冬。

思想

在回溯法中伸蚯,每次擴(kuò)大當(dāng)前部分解時(shí),都面臨一個(gè)可選的狀態(tài)集合简烤,新的部分解就通過(guò)在該集合中選擇構(gòu)造而成剂邮。這樣的狀態(tài)集合,其結(jié)構(gòu)是一棵多叉樹横侦,每個(gè)樹結(jié)點(diǎn)代表一個(gè)可能的部分解挥萌,它的兒子是在它的基礎(chǔ)上生成的其他部分解。樹根為初始狀態(tài)枉侧,這樣的狀態(tài)集合稱為狀態(tài)空間樹引瀑。
回溯法對(duì)任一解的生成,一般都采用逐步擴(kuò)大解的方式榨馁。每前進(jìn)一步憨栽,都試圖在當(dāng)前部分解的基礎(chǔ)上擴(kuò)大該部分解。它在問(wèn)題的狀態(tài)空間樹中辆影,從開始結(jié)點(diǎn)(根結(jié)點(diǎn))出發(fā)徒像,以深度優(yōu)先搜索整個(gè)狀態(tài)空間黍特。這個(gè)開始結(jié)點(diǎn)成為活結(jié)點(diǎn)蛙讥,同時(shí)也成為當(dāng)前的擴(kuò)展結(jié)點(diǎn)。在當(dāng)前擴(kuò)展結(jié)點(diǎn)處灭衷,搜索向縱深方向移至一個(gè)新結(jié)點(diǎn)次慢。這個(gè)新結(jié)點(diǎn)成為新的活結(jié)點(diǎn),并成為當(dāng)前擴(kuò)展結(jié)點(diǎn)翔曲。如果在當(dāng)前擴(kuò)展結(jié)點(diǎn)處不能再向縱深方向移動(dòng)迫像,則當(dāng)前擴(kuò)展結(jié)點(diǎn)就成為死結(jié)點(diǎn)。此時(shí)瞳遍,應(yīng)往回移動(dòng)(回溯)至最近的活結(jié)點(diǎn)處闻妓,并使這個(gè)活結(jié)點(diǎn)成為當(dāng)前擴(kuò)展結(jié)點(diǎn)÷有担回溯法以這種工作方式遞歸地在狀態(tài)空間中搜索由缆,直到找到所要求的解或解空間中已無(wú)活結(jié)點(diǎn)時(shí)為止。


四皇后問(wèn)題回溯模型

解題框架

對(duì)于回溯法的求解模型一般有兩種猾蒂,遞歸解法及非遞歸解法均唉。

非遞歸法

List result, i;
init(result, n);//初始化解結(jié)果
i = 1;
while (i>0)
{
  if(i > n) {   
      //搜索到一個(gè)解,輸出肚菠;
      //回溯
      i--;
  }
  else { 
        set(result, i, j);//賦初值或嘗試下一個(gè)值
        for (j = 下界; j <= 上界; j++) {
             if (constaint(result, j)) {
                break;
             }
        }
        if(滿足條件)
        {
             i = i + 1;
        }
        else {
            清理所占的狀態(tài)空間舔箭;            
            // 回溯
            i = i – 1; 
        }
}

遞歸法

void backTrace(int i) {
    if(i == 1) {
        init(result, n);
    }
    if(i > n) {
        //找到一個(gè)解,輸出
    } else {
        for (int j = 下界; j <= 上界; j++) {
            set(result, i, j);
            if(constraint(r, i)) {
                if(i <= n) {
                    backTrace(i + 1);
                }
            }
        }
    }
}

八皇后問(wèn)題求解

class Queen {
    int n;
    List<List<Integer>> result = new ArrayList<>();

    public Queen(int n) {
        this.n = n;
    }

    boolean conflict(List<Integer> state, int x) {
        for (int i = 1; i < x; i++) {
            if (state.get(i).equals(state.get(x)) || x - i == Math.abs(state.get(x) - state.get(i))) {
                return true;
            }
        }
        return false;
    }

    void init(List<Integer> list, int size) {
        for (int i = 0; i <= size; i++) {
            list.add(0);
        }
    }

    void reInit(List<Integer> list, int size) {
        for (int i = 2; i <= size; i++) {
            list.set(i, 0);
        }
    }

    void queen() {
        int i = 1;
        List<Integer> r = new ArrayList<>(n + 1);
        init(r, n);
        while (i > 0) {
            if (i > n) {
                //找到一組解
                ArrayList<Integer> list = new ArrayList<>(r.size() - 1);
                for (int index = 1; index < r.size(); index++) {
                    list.add(r.get(index));
                }
                result.add(list);
                //找到一組解后同樣回溯
                i = i - 1;
            } else {
                //找到第i行對(duì)應(yīng)的合適的列
                int j = r.get(i);
                r.set(i, j + 1);
                for (j = r.get(i); j <= n; j++) {
                    r.set(i, j);
                    if (!conflict(r, i)) {
                        break;
                    }
                }
                if (j <= n) {
                    //找到了合適位置蚊逢,繼續(xù)下一個(gè)
                    i++;
                } else {
                    //回溯
                    r.set(i, 0);
                    i--;
                }
            }
        }
    }

    List<Integer> r = new ArrayList<>(n);
    void queenRecurse(int i) {
        if(i == 1) {
            init(r, n);
        }
        if(i > n) {
            ArrayList<Integer> list = new ArrayList<>(r.size() - 1);
            for (int index = 1; index < r.size(); index++) {
                list.add(r.get(index));
            }
            result.add(list);
        } else {
            for (int j = 1; j <= n; j++) {
                r.set(i, j);
                if(!conflict(r, i)) {
                    if(i <= n) {
                        queenRecurse(i + 1);
                    }
                }
            }
        }
    }

    void print() {
        System.out.println(n + " queen problem has " + result.size() + " results!");
        for (int i = 0; i < result.size(); i++) {
            List<Integer> list = result.get(i);
            for (Integer in : list) {
                System.out.print(in + " ");
            }
            System.out.println();
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末层扶,一起剝皮案震驚了整個(gè)濱河市箫章,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌镜会,老刑警劉巖炉抒,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異稚叹,居然都是意外死亡焰薄,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門扒袖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)塞茅,“玉大人,你說(shuō)我怎么就攤上這事季率∫笆荩” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵飒泻,是天一觀的道長(zhǎng)鞭光。 經(jīng)常有香客問(wèn)我,道長(zhǎng)泞遗,這世上最難降的妖魔是什么惰许? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮史辙,結(jié)果婚禮上汹买,老公的妹妹穿的比我還像新娘。我一直安慰自己聊倔,他們只是感情好晦毙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耙蔑,像睡著了一般见妒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上甸陌,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天须揣,我揣著相機(jī)與錄音,去河邊找鬼邀层。 笑死返敬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的寥院。 我是一名探鬼主播劲赠,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了凛澎?” 一聲冷哼從身側(cè)響起霹肝,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎塑煎,沒(méi)想到半個(gè)月后沫换,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡最铁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年讯赏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冷尉。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡漱挎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雀哨,到底是詐尸還是另有隱情磕谅,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布雾棺,位于F島的核電站膊夹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捌浩。R本人自食惡果不足惜放刨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嘉栓。 院中可真熱鬧宏榕,春花似錦拓诸、人聲如沸侵佃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)馋辈。三九已至,卻和暖如春倍谜,著一層夾襖步出監(jiān)牢的瞬間迈螟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工尔崔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留答毫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓季春,卻偏偏與公主長(zhǎng)得像洗搂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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