1. 程式人生 > 其它 >AcWing843. n-皇后問題(C++演算法)

AcWing843. n-皇后問題(C++演算法)

技術標籤:DFSdfsc++演算法

1、題目:
n-皇后問題是指將 n 個皇后放在 n∗n 的國際象棋棋盤上,使得皇后不能相互攻擊到,即任意兩個皇后都不能處於同一行、同一列或同一斜線上。

在這裡插入圖片描述

現在給定整數n,請你輸出所有的滿足條件的棋子擺法。

輸入格式
共一行,包含整數n。

輸出格式
每個解決方案佔n行,每行輸出一個長度為n的字串,用來表示完整的棋盤狀態。

其中”.”表示某一個位置的方格狀態為空,”Q”表示某一個位置的方格上擺著皇后。

每個方案輸出完成後,輸出一個空行。

輸出方案的順序任意,只要不重複且沒有遺漏即可。

資料範圍
1≤n≤9

輸入樣例:
4
輸出樣例:
.Q…
…Q
Q…
…Q.

…Q.
Q…
…Q
.Q…

2、基本思想:
法一:DFS
按行(u)搜尋,規定每行只放一個皇后,在每行中確定列(i),確定了的皇后所在的列(col)、對角線(dg)、反對角線(udg)會被標記(q[u][i] = ‘Q’;col[i] = dg[i + u] = udg[u - i + n] = true;),再繼續搜尋下一行(dfs(u + 1);)。每一組確定完都要將棋盤迴歸上一次搜尋的狀態(q[u][i] = ‘.’; col[i] = dg[i + u] = udg[u - i + n] = false;)。

小技巧:對於 n * n 矩陣,在標記對角線時,按照座標,正對角線的方程是:行 = 列 + 常數 -> 常數 = 行 - 列,反對角線的方程是:行 = - 列 + 常數 ->常數 = 行 + 列。為了防止做減法產生負數導致陣列下標越界,對於正對角線可以 (行 - 列 + n)。

法二:逐個搜尋

3、C ++ 程式碼如下(該程式碼引用AcWing網站程式碼)

#include <iostream>

using namespace std;

const int N = 19;

int n;//n * n矩陣 
char q[N][N];//存棋盤 
bool col[N], dg[N], udg[N];//列,正對角線,反對角線 

void dfs(int u)//深搜每一行,並規定每一行只確定一個皇后 ,u表示行,i表示列 
{
	if (u == n)
	{
		for (int i = 0; i < n; i ++)
		{
			for (int j =
0; j < n; j ++) { cout << q[i][j]; } cout << endl; } } for (int i = 0; i < n; i ++)//確定在某一行的哪一列 { if (!col[i] && !dg[i + u] && !udg[u - i + n]) { q[u][i] = 'Q'; col[i] = dg[i + u] = udg[u - i + n] = true; dfs(u + 1); q[u][i] = '.'; col[i] = dg[i + u] = udg[u - i + n] = false; } } } int main() { cin >> n; for (int i = 0; i < n; i ++) { for (int j = 0; j < n; j ++) { q[i][j] = '.'; } } dfs(0); return 0; }//該程式碼引用AcWing網站程式碼

注意事項:
每次確定列之後一定要還原到上一次的狀態。