n皇后問題--回溯法,以DFS的方式搜尋

LLXL發表於2018-06-03
所謂一山不能容二虎,在 n×n 的棋盤上放置彼此不受攻擊的 n 個皇后。按照國際象棋的規則,皇后可以攻擊與

之在同一行、同一列、同一斜線上的棋子。設計演算法在 n×n 的棋盤上放置 n 個皇后,使其彼此不受攻擊。

輸入:

4

輸出:

2 4 1 3

3 1 4 2

可行方案數:2

問題分析:

題目要求不同行不同列不同斜線上,因為約束條件太多和考慮複雜度,我們不可能直接每個都列舉,可以先以行為主導,每行只放一個,找到可行的位置後就進行下一行的搜尋,當某個位置放第t個皇后時,需要判斷與前面已經放好的t-1個皇后的列和對角線時候相同,都不相同就可以在該位置放t皇后,判斷是否在同一對角線可以用兩位置行的差的絕對值和列的差的絕對值是否相等,可以以深度優先搜尋的方式進行搜尋,在t行的第i列判斷時候可以放,可以放就向深一行進行搜尋,不可以放就繼續判斷i+1,因為是n行n列的棋盤有n個皇后,說明每一行每一列都已經有一個且只有一個皇后,如果在第t行全部搜素都沒有可行的位置說明下面幾行繼續放也沒意義,這時就需要回溯,返回上一行繼續搜尋,直到n個皇后放完,當一種方案確定後也需要回溯繼續搜尋時候還有另外放方案。

程式碼:

#include<iostream>
#include<math.h>
using namespace std;
#define M 105
int n;//皇后
int x[M];//第M個皇后放在M行X[M]列
int num;//可行方案的個數
bool place(int t)
{//判斷第t個皇后是否能放在第i列
	bool ok = true;
	for (int i = 1; i < t; i++)//判斷i列是否與前t-1個皇后的位置衝突
	{
		if (x[i] == x[t] || (t - i) == fabs(x[t] - x[i]))//因為已經是以行為主導,所以判斷是隻需要判斷列和對角線
		{
			ok = false;
			break;
		}
	}
	return ok;
}
void Backtrack(int t)
{
	if (t > n)//如果當前位置為n,則說明已經得到一個方案
	{
		num++;
		for (int i = 1; i <= n; i++)//列印路徑
			cout << x[i] << " ";
		cout << endl;
	}
	else
		for (int i = 1; i <= n; i++)
		{
			x[t] = i;//第t行第x[t]列,也是此時的第i列
			if (place(t))
				Backtrack(t + 1);//如果不衝突。則進行下一行的搜尋
		}
}
int main()
{
	cin >> n;
	num = 0;
	Backtrack(1);
	cout << "可行方案數:" << num << endl;
	return 0;
}

相關文章