《算法笔记》8.1小节——搜索专题->深度优先搜索(DFS)问题 D: 【递归入门】n皇后 问题(原始的8皇后问题)
题目描述
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
输入
一个整数n( 1 < = n < = 10 )
输出
每行输出对应一种方案,按字典序输出所有方案。每种方案顺序输出皇后所在的列号,相邻两数之间用空格隔开。如果一组可行方案都没有,输出“no solute!”
样例输入
4
样例输出
2 4 1 3
3 1 4 2
分析:可以用生成全排列的方法表示皇后的坐标,其中第一个坐标用存储数组的位置下标代替,生成的全排列就是皇后的第二个坐标。显然第一个坐标和第二个坐标都不会重复,即皇后不会处于同一排或者同一列上,因此只需要判断是否处在同一斜线上。这样在生成全排列的时候就可以提前去掉不可能的组合,能够生成的排列一定是符合要求的。
如果两个皇后处于同一斜线上,这条斜线的斜率绝对值一定为1,即两个皇后的横坐标之差等于纵坐标之差。前面提到横坐标是存储数组的下标,纵坐标是生成的排列,这样相减后取绝对值进行比较即可。
#include<algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <queue>
#include <stack>
#include <ctime>
#include <cmath>
#include <map>
#include <set>
#define ll long long
#define INF 0x3f3f3f3f
#define db1(x) cout<<#x<<"="<<(x)<<endl
#define db2(x,y) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<endl
#define db3(x,y,z) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<endl
#define db4(x,y,z,a) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#a<<"="<<(a)<<endl
using namespace std;
void getans(int n,int index,int *num,int *flag,int &ans)
{
if(index==n)
{
ans++;
for(int i=0;i<n;++i)
i==0?printf("%d",num[i]):printf(" %d",num[i]);
printf("\n");
return;
}
for(int i=1;i<=n;++i)
{
if(flag[i]==0)
{
int f=1;
for(int j=0;j<index;++j)
{
if((int)fabs(num[j]-i)==(int)fabs(index-j))
{
f=0;break;
}
}
if(f)
{
num[index]=i,flag[i]=1;
getans(n,index+1,num,flag,ans);
flag[i]=0;
}
}
}
return;
}
int main(void)
{
#ifdef test
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
clock_t start=clock();
#endif //test
int n;
while(~scanf("%d",&n))
{
if(n<=3)
{
printf("no solute!\n");
continue;
}
int num[n+5]={0},flag[n+5]={0};
int ans=0;
getans(n,0,num,flag,ans);
}
#ifdef test
clockid_t end=clock();
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
printf("\n\n\n\n\n");
cout<<"Total time:"<<endtime<<"s"<<endl; //s为单位
cout<<"Total time:"<<endtime*1000<<"ms"<<endl; //ms为单位
#endif //test
return 0;
}