N皇后問題隨機搜尋(線性衝突檢測)

2021-10-11 13:31:09 字數 1969 閱讀 1486

問題:

對於n皇后問題,可以通過回溯法來進行求解,能夠找到所有的可行解。隨著規模的增大,可以通過隨機搜尋的方式來快速地獲得乙個可行的解。

隨機搜尋的過程中,通過皇后之間的衝突數來衡量結果的好壞。從第一行開始,每個皇后輪詢地和後續的皇后進行檢查,看是否存在衝突,時間複雜度為o(n^2)。隨著時間上公升,衝突計算部分是明顯的瓶頸。

可以通過其他方法將衝突計算時間複雜度優化為o(n)。網上的方法,現成的**也不少。但似乎沒有太細緻地說這件事情,因此有了本文。簡單地說一說,希望能夠方便讀者快速理解。

這裡通過乙個一維陣列a來表示皇后的位置,對於a[i],i表示的是第i行,a[i]表示第i行的皇后放置在第a[i]列。

對於a[3]=表示的皇后如下:

通過一維陣列定義的情況下,不會出現行衝突和列衝突的情況,只需要的考慮對角線衝突的情況。

**中白底部分的數值是行和列編號的相加,可以看出來,在一條對角線上的元素行列相加的和都相同。換句話說,對於行列相加值相同的元素,會在一條對角線上。

下面舉個例子,a[8]=(此處下標從1開始)的放置方法如下。行列值為3的皇后兩個,行列值為9的皇后有4個,值為15的皇后有2個。同一條對角線上兩兩衝突,衝突數為(c-1)*c/2,如行列值為3的衝突數為1。

行列值共有2n種情況,掃瞄a陣列,並通過乙個長度為2n的陣列就能夠統計整個a陣列的可能行列情況。

上面是反對角線的情況,正對角線也相同。行列值的計算稍作下改動,改為row + n-column +1 。

衝突皇后都統計出來之後,正反對角線陣列均掃瞄一次,就能計算衝突數。

int

conflicts

(std::vector<

int>

&vec)

for(

int i =

0; i < diag.

size()

; i++

)return count;

}

完整**如下:

#include

#include

#include

#include

#include

#include

intconflictcount

(std::vector<

int>

&candidate,std::vector<

int> diagonallinevec,std::vector<

int> rdiagonallinevec)

for(

int i =

0; i <

2* n; i++

)return count;

}void

queeninit

(std::vector<

int>

&vec)

std::vector<

int>

queenlocalsearch

(unsigned

int num)

}queeninit

(tmpresult)

; lowestconflictcount=

conflictcount

(tmpresult,diagonallinevec,rdiagonallinevec);}

return tmpresult;

}int

main()

; std::vector<

int> testnum

;for

(int i=

0;isize()

;i++

)return0;

}

N皇后問題(搜尋)

problem description 在n n的方格棋盤放置了n個皇后,使得它們不相互攻擊 即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。你的任務是,對於給定的n,求出有多少種合法的放置方法。input 共有若干行,每行乙個正整數n 10,表示棋盤和皇后的數量 如...

DFS搜尋 N皇后問題

八皇后問題,是乙個古老而著名的問題,是回溯演算法的典型案例。該問題是國際西洋棋棋手馬克斯 貝瑟爾於1848年提出 在88格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。高斯認為有76種方案。1854年在柏林的象棋雜誌上不同的作者發表了4...

簡單搜尋01 N皇后問題

題目大意 在n n的方格棋盤放置了n個皇后,使得它們不相互攻擊 即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。你的任務是,對於給定的n,求出有多少種合法的放置方法。解題思路 回溯法。要先打表,不然tle。自覺已經精簡到最簡了結果還是tle的痛苦人民得到大佬的提示要先...