八皇后問題

2021-07-08 09:02:09 字數 4024 閱讀 5106

兩個版本。思路大體相同,都是用的回溯。不過資料結構上的版本不太容易懂。先寫上來吧。

struct queen ;

bool

operator==(queen const& q)const

bool

operator != (queen const& q)const

};

static

int ncheck = 0;

static

int nresult = 0;

void placequeens(int n)

else

//這裡用if,else,因為不能保證回溯後是否能繼續執 //行,乾脆用分支,用下一次的if判斷來保證

if (q.y //如果找到乙個可以放置的地方,就將其入棧,判斷能否 //輸出完整的解,並搜尋下一行,從第0列開始

}while ((q.x >0) || (q.y < n))//退出迴圈的條件是搜尋到第0行第n列

}

一些總結:

①退出迴圈的條件是搜尋到第0行第n列

②進入程式後會發生以下幾種情況:

(一)滿足迴圈條件,沒有越界,進過迴圈判斷後可以放置,並且不是最後一行,那麼下一步就是入棧並執行下一行

(二)滿足迴圈條件,沒有越界,進過迴圈判斷後可以放置,是最後一行,下一步仍然是執行下一行,但是會回溯

(三)滿足迴圈條件,沒有越界,進過迴圈判斷後沒有可以放置的位置,那麼經過迴圈之後q.y應該是等於n的,跳過入棧,到下次迴圈會回溯

(四)solu.size() >= n,即棧滿了,此時像越界一樣處理,回溯並y++

(五)q.y >=n,越界,需要回溯

③相比於遞迴來說比較難理解,但是空間複雜度較少,而且通過剪枝也得到了很好的優化。

///

八皇后遞迴版

const

int normalize = 9;

int num;

int q[9];

bool s[9];

bool l[17]; //用來存放對角線標記的

bool y[17];

void

try(int col)

for (int row = 1; row <= 8; row++)}}

int main()

try(1);

return

0;}

感覺遞迴版沒啥好說的,簡單便捷,回溯也方便》。。。

11.26新增

這次是lisp版的,太簡潔了,lisp果然是神書…

(define

(queens board-size)

(define

(queen-cols k)

(if (=k

0)(list

empty-board)

(filter

(lambda

(positions)

(safe? k positions))

(flatmap

(lambda

(rest-of-queens)

(map

(lambda

(new-row)

(adjoin-position new-row k rest-of-queens))

(enumerate-interval

1 board-size)))

(queen-cols

(-k1))))))

(queen-cols board-size))

(define empty-board '())

;定義空棋盤

(define

(adjoin-position

new-row k rest-of

-queens)

(cons new

-row rest-of

-queens))

;新增皇后

刪除不安全的皇后

(define

(safe? k position)

(iter-check

(car position)

(cdr position)

1))(define

(iter-check row-of-new-queen rest-of-queens i)

(if (null? rest-of-queens)

; 下方所有皇后檢查完畢,新皇后安全

#t(let

((row-of-current-queen

(car rest-of-queens)))

(if (or

(= row-of-new-queen row-of-current-queen)

; 行碰撞

(= row-of-new-queen (+

i row-of-current-queen))

; 右下方碰撞

(= row-of-new-queen (-

row-of-current-queen i)))

; 左下方碰撞

#f(iter-check row-of-new-queen (cdr rest-of-queens)

; 繼續檢查剩餘的皇后

(+ i1))))))

; 更新步進值

解釋:rest-of-queens是在前k-1列防止k-1個皇后的一種方式,new-row是在第kie放置所考慮的行編號。adjoin-position是將乙個新的行列格局加入到乙個格局集合;empty-board是乙個空的格局集合,safe?是確定新的格局中的kie的皇后是否是安全的。

讓我們從表達方式開始說明。

表達出來就是list(6 3 1 7 5 8 2 4)

因為題目要求給出八皇后問題的所有解法,所以 queens 求出的最終結果將是乙個二維列表: (list (list 6 3 1 7 5 8 2 4) (list …) (list …) …) 。

(define

(safe? k position)

(iter-check

(car position)

(cdr position)

1))(define

(iter-check row-of-new-queen rest-of-queens i)

(if (null? rest-of-queens)

; 下方所有皇后檢查完畢,新皇后安全

#t(let

((row-of-current-queen

(car rest-of-queens)))

(if (or

(= row-of-new-queen row-of-current-queen)

; 行碰撞

(= row-of-new-queen (+

i row-of-current-queen))

; 右下方碰撞

(= row-of-new-queen (-

row-of-current-queen i)))

; 左下方碰撞

#f(iter-check row-of-new-queen (cdr rest-of-queens)

; 繼續檢查剩餘的皇后

(+ i1))))))

; 更新步進值

safe 這個函式,呼叫了乙個iter-check函式,iter-check函式傳入的引數有三個(其實是兩個),新加入的行,還有之前的行,在這裡之前的行我們已經可以保證它是符合規定的。

然後就是遍歷檢查了,之前存的時候從上向下存的乙個好處在這就能體現了,從上向下便利檢查每乙個數字,並且也要看對角線是否滿足要求,如果到最後都檢查完了就是成功了,否則就是失敗。

八皇后問題

八皇后問題 ackarlix 八皇后問題是乙個古老而著名的問題,是回溯演算法的典型例題。該問題是十九世紀著名的數學家高斯 1850 年提出 在 8x8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。高斯認為有 76種方案。1854 年在...

八皇后問題

include iostream.h int a 8 8 棋盤 int r 8 結果 int i,j int count 0 void init i j 0 int judge int x,int y for int mi x 1,mj y mi 1 mi for int ri x 1,rj y 1...

八皇后問題

package quess 由於八個皇后的任意兩個不能處在同一行,那麼這肯定是每乙個皇后佔據一行。於是我們可以定義乙個陣列columnindex 8 陣列中第i個數字表示位於第i行的皇后的列號。先把columnindex的八個數字分別用0 7初始化,接下來我們要做的事情就是對陣列columninde...