题目描述:n皇后是指在一个n行n列的棋盘上,将n个皇后摆放在不同的位置,不能出现在同一行,同一列,同一斜线,问有多少种解法。
思路一:
建立一个二维数组,初始化都为0,(皇后的位置置1)从第一行开始放皇后,列有八种情况,从第一种情况开始,如果这个位置的上面的列,左上正对角线,以及右上正对角线没有皇后,则是安全的,这个位置可以放置皇后,继续递归下一行,否则继续探索这一行的其他列,如果这一行的所有列都不能放下皇后,则向上返回一层(从上一行的其他满足情况的列又开始向下探索)。 当有一种解法时打印棋盘,开始向上回溯探索当前列到n-1列是否有满足情况的,如果有则继续向下递归没有则向上一行回溯 直到回溯到第0行的第n-1列然后向下递归,没有向上的回溯时才完毕
思路二:
n个皇后分别在不同行的不同列,可以先将1–n进行排列组合,每个数的每个位置代表对应行的列,将所有的排列组合去除掉在同一斜线上的情况,剩下的就是n皇后的题解
代码1:
#include<string.h>
#include <iostream>
#include <cmath>
using namespace std;
int _count=1;
int judge_safe(int check[8][8],int row,int m,int n)
{
//判断当前位置的的前面数组里有没有和当前位置在同一条直线上
//分成四部分,左上角,左下角,右上角和右下角
//列
for(int i=0;i<m;i++)
{
if(check[i][n]==1)
return 1;
}
//左上角
for(int i=m-1,j=n-1;i>=0&&j>=0;i--,j--)
{
if(check[i][j]==1)
return 1;
}
//右上角
for(int i=m-1,j=n+1;i>=0&&j<row;i--,j++)
{
if(check[i][j]==1)
return 1;
}
return 0;
}
void eight_queens(int check[8][8],int row,int m)//m表示当前行
{
if(m==8)
{
cout<<"-----------第--"<<_count<<"-----种-----------------"<<endl;
//已经全部找到了一组满足情况的棋盘
for(int i=0;i<row;i++)
{
for(int j=0;j<row;j++)
{
cout<<check[i][j]<<" ";
}
cout<<endl;
}
_count++;
}
//先从第一行开始放皇后,从0~7列一个一个试,如果所下的地方与之前下的地方不冲突,
//则当前位置是安全的,并将这个位置置1
for(int j=0;j<row;j++)
{
if( judge_safe(check,row,m,j)==0)//调用judge_safe函数来判断所下的位置是否安全
{ //如果j这一列都会与上面的冲突,则回溯到上一行,并从上一行的j+1的地方又开始判断
//为避免不能一次性下对地方,所以现将这一行的元素都置0,
//再将check[row][j]置1,否则一行可能会出现多个1
check[m][j]=1;
//第row行已经下好继续第row+1
eight_queens(check,row,m+1);
check[m][j]=0;//如果不满足情况,则恢复之前的状态
}
}
}
int main()
{
//定义并初始化一个8*8的棋盘
//棋盘刚开始的元素都为0,将皇后的位置置为1.
int check[8][8]={0};
eight_queens(check,8,0);
return 0;
}
代码2:
#include<string.h>
#include <iostream>
#include <cmath>
using namespace std;
int count=1;
void _swap(int a,int b,int *arr)
{
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
void is_ok(int check[9],int N)
{
//如果在同一条斜线上则返回0,从一个数开始判断它后面的元素是否和他在一条线上
// 如果 j-i=abs(check[i]-check[j]);则在同一条线上
for(int i=1;i<=N-1;i++)
{
for(int j=i+1;j<=N;j++)
{
if(j-i==abs(check[i]-check[j]))
// if(j-i==check[i]-check[j]||j-i==check[j]-check[i])
return ;
}
}
cout<<"---第--"<<count<<"--种---"<<endl;
for(int i=1;i<=N;i++)
cout<<i<<" "<<check[i]<<endl;
++count;
}
//N为8,k代表待排列的位置
void eight_queens(int check[9],int N,int k)
{
if(k==9)
{
is_ok(check,N);
}
for(int i=k;i<=N;i++)
{
_swap(i,k,check);
eight_queens(check,N,k+1);
_swap(i,k,check);//回溯到原来的状态
}
}
int main()
{
//八皇后,每一列只存放一个位置,可以先将八个数进行全排列,
//将所有的排列组合中去掉在同一条斜线上的组合,剩下的就是八皇后的解
int check[9]={0,1,2,3,4,5,6,7,8};
eight_queens(check,8,1);
return 0;
}