八皇后的遞歸解法

最近在看PiL3,今天在做習(xí)題的時候遇見了八皇后問題,當(dāng)時示例代碼并沒有仔細看,等到寫的時候發(fā)現(xiàn)老是有問題。后來去查了下八皇后問題的描述,發(fā)現(xiàn)自己雖然知道這個問題很久了卻沒有真正理解過,真為自己汗顏。

八皇后問題

以下資料來自WikiPedia:

八皇后問題是一個以國際象棋為背景的問題:如何能夠在8×8的國際象棋棋盤上放置八個皇后,使得任何一個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處于同一條橫行、縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題:這時棋盤的大小變?yōu)閚×n,而皇后個數(shù)也變成n。當(dāng)且僅當(dāng)n = 1或n ≥ 4時問題有解。

一個簡單的遞歸算法

這個算法來自于PiL3中,我在做習(xí)題的時候?qū)⑵渥约簩崿F(xiàn)了一遍,思路是一樣的,下面介紹一下。
首先定義了2個全局變量,N表示棋盤的大小,solved代表問題是否已解決。
printBoard用來打印當(dāng)前棋盤,皇后用X表示,空格用-表示。
validPos的作用是判斷當(dāng)前棋盤上能否在n行pos列上放置新棋子。

addQueen是算法的核心函數(shù),也是被遞歸調(diào)用的函數(shù)。board代表當(dāng)前的棋盤,n表示當(dāng)前放置棋子的行數(shù)。
當(dāng)n大于N時表明當(dāng)前棋盤已經(jīng)有解了,直接打印即可。
當(dāng)n小于N時,嘗試當(dāng)前行n上在pos列放置棋子,如果位置合適則在棋盤上記錄該棋子,并繼續(xù)在下一行添加新棋子(調(diào)用addQueen(board,n+1))。如果不合適,則舍棄當(dāng)前棋盤,不再遞歸調(diào)用自身,我一開始沒有仔細看這里,導(dǎo)致我沒理解這個解法如何只對符合規(guī)則的棋盤繼續(xù)求解。

總結(jié):與最常用最容易想到的回溯法相比,遞歸的方法顯得簡單粗暴,不過代碼也確實簡單了不少。

Lua實現(xiàn)如下:

local N=8
local solved=false
local function printBoard(board)
    if solved then
        return
    end
    for i=1, N do
        for j=1, N do
            io.write(board[i]==j and "X" or "-", " ")
        end
        io.write("\n")
    end
    io.write("\n")
    solved = true
end
local function validPos(board, row, pos)
    for i=1, row-1 do
        if (board[i] == pos) or
            (row-i == math.abs(pos - board[i])) then
            return false
        end
    end
    return true
end

local function addQueen(board, n)
    if n>N then
        printBoard(board)
    else
        for pos=1, N do
            if validPos(board, n, pos) then
                board[n]=pos
                addQueen(board, n+1)
            end
        end
    end
end

addQueen({},1)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容