N皇后问题 HDU - 2553(回溯/DFS/打表)
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
我的题解:n皇后问题应该算是最经典的回溯算法的例子.不过我在写的DFS递归超时了,气的我打了个表交上去.hhhh
用非递归的方法写可能就不会超了,但我太懒了,打表大法好
我本来使用二维数组,参考了网上的blog,改成了一维数组,太强了,我怎么就想不到???!!!!!!!
大概就3个步骤,逐行逐行的试,可以保证每行只有一个皇后;检查同一列是否有皇后;检查对角线是否有皇后.
DFS
#include <bits/stdc++.h>
const int N=20;
using namespace std;
//int mp[N][N];
int mp[N];//使用一维数组
int ans;
int n;
/*
void op(){
for(int i=1;i<=n;i++) printf("%d ",mp[i]); puts("");
}*/
bool ck(int x,int y){
for(int i=1;i<=x-1;i++) if(x-i==abs(mp[i]-y)) return false;
return true;
}
bool isempty(int m){
for(int i=1;i<=n;i++) if(mp[i]==m) return false;
return true;
}
void dfs(int now,int end){
for(int i=1;i<=end;i++){
if(ck(now,i)&&isempty(i)){
if(now==end) ans++;
else mp[now]=i,dfs(now+1,end),mp[now]=0;
}
}
}
int Nqueue(int n){
memset(mp,0,sizeof(mp));
ans=0;
dfs(1,n);
return ans;
}
int main()
{
while(cin>>n&&n!=0){
cout<<Nqueue(n)<<endl;
}
//cout << "Hello world!" << endl;
return 0;
}
打表
#include <iostream>
using namespace std;
int a[11]={0,1,0,0,2,10,4,40,92,352,724};
int main()
{
int n;
while(cin>>n&&n!=0){
cout<<a[n]<<endl;
}
//cout << "Hello world!" << endl;
return 0;
}