问题 D: 【递归入门】n皇后 问题(原始的8皇后问题)
[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB
题目描述
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
输入
一个整数n( 1 < = n < = 10 )
输出
每行输出对应一种方案,按字典序输出所有方案。每种方案顺序输出皇后所在的列号,相邻两数之间用空格隔开。如果一组可行方案都没有,输出“no solute!”
样例输入 Copy
4
样例输出 Copy
2 4 1 3
3 1 4 2
#include <bits/stdc++.h>
using namespace std;
const int maxn=22;
int n;
int a[maxn];//当前排列;
bool hashTable[maxn]= {false};//第i列是否被使用;
int cnt=0;
void prints()
{
for(int i=1; i<=n; i++)
{
for(int j=i+1; j<=n; j++)//遍历全排列;
{
if(abs(i-j)==abs(a[i]-a[j]))
{
return;
}
}
}
cnt++;
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<"\n";
}
void dfs(int index)
{
if(index>n)
{
prints();
}
for(int i=1; i<=n; i++)
{
if(!hashTable[i])
{
hashTable[i]=true;//第i列已被使用;
a[index]=i;//第index个皇后放入第i列;
dfs(index+1);//处理第i+1个皇后;
hashTable[i]=false;//复原
}
}
}
int main()
{
scanf("%d",&n);
cnt=0;
dfs(1);//从排列第一个皇后开始;
if(cnt==0)
{
printf("no solute!");
}
return 0;
}
改进法:回溯剪枝
#include <bits/stdc++.h>
using namespace std;
const int maxn=22;
int n;
int a[maxn];//当前排列;
bool hashTable[maxn]= {false};//第i列是否被使用;
int cnt=0;
void prints()
{
cnt++;
for(int i=1; i<=n; i++)
{
cout<<a[i]<<" ";
}
cout<<"\n";
}
void dfs(int index)
{
if(index>n)
{
prints();
}
for(int i=1; i<=n; i++)
{
if(!hashTable[i])
{
bool flag=true;
for(int j=1; j<index; j++)
{
if(abs(index-j)==abs(i-a[j]))
{
flag=false;//与之前某一个在对角了,这种排列不符合,不用继续dfs了;
break;
}
}
if(flag)
{
hashTable[i]=true;//i使用;
a[index]=i;//index位置填入i;
dfs(index+1);//处理index+1位;
hashTable[i]=false;
}
}
}
}
int main()
{
scanf("%d",&n);
cnt=0;
dfs(1);//从排列第一个皇后开始;
if(cnt==0)
{
printf("no solute!");
}
return 0;
}