思路:
在 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;
}