《數(shù)據(jù)結構與算法之美》30——回溯算法

什么是回溯算法

回溯算法實際上一個類似枚舉的搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當發(fā)現(xiàn)已不滿足求解條件時巾陕,就 “回溯” 返回,嘗試別的路徑纪他。

回溯法是一種選優(yōu)搜索法鄙煤,按選優(yōu)條件向前搜索,以達到目標茶袒。但當探索到某一步時梯刚,發(fā)現(xiàn)原先選擇并不優(yōu)或達不到目標,就退回一步重新選擇薪寓,這種走不通就退回再走的技術為回溯法亡资,而滿足回溯條件的某個狀態(tài)的點稱為 “回溯點”。許多復雜的向叉,規(guī)模較大的問題都可以使用回溯法锥腻,有“通用解題方法”的美稱。

回溯算法的基本思想是:從一條路往前走植康,能進則進旷太,不能進則退回來,換一條路再試。

八皇后問題

我們學習了什么是回溯算法供璧,聽起來很簡單存崖,但具體怎么使用呢?下面我們通過一個例子來說明回溯算法的用法睡毒。

八皇后問題:有一個8X8的棋盤来惧,希望往里放8個棋子(皇后),每個棋子所在的行演顾、列供搀、對角線都不能有另一個棋子,找到所有滿足這種要求的放棋方式钠至。

解題思路:把這個問題劃分成8個階段葛虐,依次將8個棋子放到第一行、第二行棉钧、第三行....第八行屿脐。在放置的過程中,不停地檢查當前的方法宪卿,是否滿足要求的诵。如果滿足,則跳到下一行繼續(xù)放置棋子佑钾;如果不滿足西疤,那就換一種方法,繼續(xù)嘗試休溶。

代碼實現(xiàn)如下:

public class Solution {
    int[] result = new int[8]; // 全局或成員變量代赁,下標表示行,值表示queen存儲在哪一列
    public void Cal8Queens (int row) { // 調用方式:Cal8Queens(0);
        if (row == 8) { // 8個棋子都放置好了兽掰,打印結果
            PrintQueens (result);
            return; // 8行棋子都放好了管跺,已經(jīng)沒法再往下遞歸了,所以就return
        }
        for (int column = 0; column < 8; ++column) { // 每一行都有8中放法
            if (IsOK (row, column)) { // 有些放法不滿足要求
                result[row] = column; // 第row行的棋子放到了Column列
                Cal8Queens (row + 1); // 考察下一行
            }
        }
    }

    private bool IsOK (int row, int column) { // 判斷row行column列放置是否合適
        int leftup = column - 1, rightup = column + 1;
        for (int i = row - 1; i >= 0; --i) { // 逐行往上考察每一行
            if (result[i] == column) return false; // 第i行的column列有棋子嗎禾进?
            if (leftup >= 0) { // 考察左上對角線:第i行l(wèi)eftup列有棋子嗎?
                if (result[i] == leftup) return false;
            }
            if (rightup < 8) { // 考察右上對角線:第i行rightup列有棋子嗎廉涕?
                if (result[i] == rightup) return false;
            }
            --leftup;
            ++rightup;
        }
        return true;
    }

    private void PrintQueens (int[] result) { // 打印出一個二維矩陣
        for (int row = 0; row < 8; ++row) {
            for (int column = 0; column < 8; ++column) {
                if (result[row] == column) Console.Write ("Q ");
                else Console.Write ("* ");
            }
            Console.WriteLine ();
        }
        Console.WriteLine();
    }
}

總結

回溯算法的思想非常簡單泻云,大部分情況下狐蜕,都是用來解決廣義的搜索問題:從一組可能的解中宠纯,選擇出一個滿足要求的解层释。

回溯算法非常適合用遞歸來實現(xiàn),在實現(xiàn)的過程中,剪枝操作是提高回溯效率的一種技巧廉白。利用剪枝,并不需要窮舉搜索所有的情況猴蹂,從而提高搜索效率院溺。

參考資料

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末磅轻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子聋溜,更是在濱河造成了極大的恐慌谆膳,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撮躁,死亡現(xiàn)場離奇詭異漱病,居然都是意外死亡,警方通過查閱死者的電腦和手機馒胆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門缨称,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祝迂,你說我怎么就攤上這事睦尽。” “怎么了型雳?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵当凡,是天一觀的道長。 經(jīng)常有香客問我纠俭,道長沿量,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任冤荆,我火速辦了婚禮朴则,結果婚禮上,老公的妹妹穿的比我還像新娘钓简。我一直安慰自己乌妒,他們只是感情好,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布外邓。 她就那樣靜靜地躺著撤蚊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪损话。 梳的紋絲不亂的頭發(fā)上侦啸,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天槽唾,我揣著相機與錄音,去河邊找鬼光涂。 笑死庞萍,一個胖子當著我的面吹牛,可吹牛的內容都是我干的顶捷。 我是一名探鬼主播挂绰,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼服赎!你這毒婦竟也來了葵蒂?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤重虑,失蹤者是張志新(化名)和其女友劉穎践付,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缺厉,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡永高,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了提针。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片命爬。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辐脖,靈堂內的尸體忽然破棺而出饲宛,到底是詐尸還是另有隱情,我是刑警寧澤嗜价,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布艇抠,位于F島的核電站,受9級特大地震影響久锥,放射性物質發(fā)生泄漏家淤。R本人自食惡果不足惜瑟由,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望歹苦。 院中可真熱鬧,春花似錦暂氯、人聲如沸亮蛔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至神得,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哩簿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工羡玛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人稼稿。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓讳窟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親丽啡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350