1. 程式人生 > 其它 >【ACWing】843. n-皇后問題

【ACWing】843. n-皇后問題

技術標籤:AC 搜尋、圖論與網路dfs

題目地址:

https://www.acwing.com/problem/content/845/

n n n皇后問題,在 n × n n\times n n×n的棋盤上放 n n n個皇后,使得這些皇后互相不攻擊。要求輸出所有方案。

資料範圍:
1 ≤ n ≤ 9 1\le n\le 9 1n9

思路是DFS。列舉每一行在哪一列放皇后。同時用三個變數分別存,哪些列已經放了皇后,還有哪些對角線已經放了皇后。對於對角線的判斷,我們可以分為方向從左上到右下的對角線,和方向從右上到左下的對角線兩種型別分別判斷。從左上到右下的對角線,我們規定 ( 0 , n − 1 ) (0,n-1)

(0,n1)所在的對角線是 0 0 0號, ( 0 , n − 2 ) (0,n-2) (0,n2)所在的對角線是 1 1 1號,等等,那麼對角線的號碼 k k k和上面某點的座標 ( i , j ) (i,j) (i,j)滿足 j = i + n − 1 − k j=i+n-1-k j=i+n1k,所以 k = i − j + n − 1 k=i-j+n-1 k=ij+n1;從右上到左下的對角線,我們規定 ( 0 , 0 ) (0,0) (0,0)所在的對角線是 0 0 0號, ( 0 , 1 ) (0,1) (0,1)所在的對角線是 1 1 1號,等等,那麼對角線的號碼 k k k和上面某點的座標 ( i , j ) (i,j)
(i,j)
滿足 j = − i + k j=-i+k j=i+k,所以 k = i + j k=i+j k=i+j。搜到第 n + 1 n+1 n+1行的時候說明找到了一個解,輸出答案即可。程式碼如下:

#include <iostream>
#include <cstring>
using namespace std;

void dfs(int i, int res[], int n, bool used[], bool diag[], bool udiag[]) {
    if (i == n) {
        for (int j = 0; j < n;
j++) { for (int k = 0; k < n; k++) { if (res[j] == k) cout << 'Q'; else cout << '.'; } cout << endl; } cout << endl; return; } for (int j = 0; j < n; j++) { if (used[j] || diag[i - j + n - 1] || udiag[i + j]) continue; used[j] = diag[i - j + n - 1] = udiag[i + j] = true; res[i] = j; dfs(i + 1, res, n, used, diag, udiag); used[j] = diag[i - j + n - 1] = udiag[i + j] = false; } } int main() { int n; cin >> n; int res[n]; bool used[n], diag[2 * n - 1], udiag[2 * n - 1]; memset(used, false, sizeof used); memset(diag, false, sizeof diag); memset(udiag, false, sizeof udiag); dfs(0, res, n, used, diag, udiag); return 0; }

時間複雜度 O ( n 2 n ! ) O(n^2n!) O(n2n!)(因為伴隨著剪枝,實際時間達不到這麼高),空間 O ( n ) O(n) O(n)