問題:
對於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的痛苦人民得到大佬的提示要先...