N皇后問題(個人覺得解釋的比較清晰了)(dfs回溯)

思路:

在 n*n 格的國際象棋上擺放n個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。

dfs(int row):
     每一行只放一個,放完一個queen就直接去下一行,這樣就不會出現一行有多個queen,所以判斷是否能放某個位置時,只需要判斷和之前放的所有queen是否在同一列或者對角線上(斜率±1)。
   

開個site數組 ,下標爲row,值爲col(第row行的queen放在第col列)

斜率k = Δrow / Δcol ;(相當於y / x)
所以第 i 行 的col 位置爲 site[i],想要放的位置爲row,col;

兩個點就是(i,site [i]) , (row,col)

那麼求兩點的斜率就變成了 y2-y1 = k(x2-x1)

k爲±1 那麼 兩邊直接用abs就可以了

代碼:

#include <iostream>
#include <cmath>
using namespace std;  
const int maxn=20;
int n,site[maxn],ans=0; 
//n皇后 ; site下標爲row,值爲col(第row行的queen放在第col列) ; ans方案數 
bool pan(int row,int col)
{
	for(int i=0;i<row;i++)  //遍歷row之前一行 
	{
	  if(site[i]!=-1) continue; //這個點沒放就跳過不用判斷
	  if(col==site[i] || abs(row-i)==abs(col-site[i]))
	   //在同一列或者斜率爲+-1(在對角線) 
	    return 0;
	}
	return 1;
}
void dfs(int row)
{
	if(row==n)  //row到了n 代表0~n-1這n行都已經放了,是一種方案 
	{
		ans++; //方案+1 
		return;
	}
	for(int i=0;i<n;i++)  //遍歷row行每一列 
	{
	   if(pan(row,i)) //判斷,這個位置可以放 
	   {
	   	  site[row]=i; // 第row行的queen放在第i列 
	   	  dfs(row+1);  //這一行放了,dfs下一行 
	   	  site[row]=-1; // 回溯變回-1,代表這一行還沒放 
	   } 
	}  
}
int main()
{
    cin>>n;
    fill(site,site+maxn,-1);  //初始化數組,-1代表這一行沒放queen 
    dfs(0);  //從第零行開始 
    cout<<ans;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章