題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2553
Problem Description
在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。
Input
共有若干行,每行一個正整數N≤10,表示棋盤和皇后的數量;如果N=0,表示結束。
Output
共有若干行,每行一個正整數,表示對應輸入行的皇后的不同放置數量。
Sample Input
1
8
5
0
Sample Output
1
92
10
題解:這道題一開始並沒有思路,是看了一個大佬的然後理解了自己敲出來的
思路的話,首先要搞清楚如果一行或者一列或者同在45°的一條線放了一個棋子,那麼剩下的位置就不能再放置了。
如果我們按行遍歷,那麼這三個方向都有共同點,一個是列數相等,一個是列數-行數的值相等,一個是列數+行數值相等。
這樣的話我們可以開始一個深度遍歷,先設置一個標記變量使它能夠表示這個位置是否可以放置棋子,然後一行一行的開始,然後一列挨着一列遍歷,遇到一個符合條件的就進入下一行,最後如果遍歷的行數和N相等,那麼就代表有一種方法,然後退出這層遍歷,並把剛剛標記值初始化(因爲我們已經知道這個點可以放置,但是我們遍歷下一點的時候他可能已經被標記過,然而我們目前這個方案並沒有在那個點放置,所以需要初始化)。
具體看代碼。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int vis[3][50],a[50];
int n,sum;
void dfs(int row)
{
int i;
if(row==n+1)//已經遍歷了N行
{
sum++;
return;
}
for(i=1;i<=n;i++)
{
if(vis[0][row-i+n]==0&&vis[1][i]==0&&vis[2][row+i]==0)//表示目前這三個方向沒有放置棋子
{
vis[0][row-i+n]=vis[1][i]=vis[2][row+i]=1;//標記,假設已經放置
dfs(row+1);//遍歷下一行
vis[0][row-i+n]=vis[1][i]=vis[2][row+i]=0;//返回當前行,並把標記取消
}
}
}
int main()
{
for(n=1;n<=10;n++)//先打表,不然會超時
{
sum=0;
memset(vis,0,sizeof(vis));
dfs(1);
a[n]=sum;
}
int x;
while(scanf("%d",&x),x)
{
printf("%d\n",a[x]);
}
return 0;
}