n皇后问题
问题描述:现有一个n*n格的棋盘,并且有n个皇后。要求将n个皇后放入棋盘,任意两个皇后不能处于同一行、同一列和同一斜线。输出所有解法
分析思路:分析该问题,可以使用递归回溯问题法解决,并且n皇后问题为回溯问题中的排列树。在递归的过程中,对不满足条件的分支进行减支来提高运行效率。首先,我们在递归时循环n次,因为有n个皇后,并且任意两个皇后不能处于同一行,所以肯定每一行都有一个皇后,所以皇后的行号在递归时即可确定;要满足任意两个皇后不能处于同一列,只需要定义一个长度为n的数组,数组中保存1~n的下标,每次循环时只需要做下标的全排列即可保证每个皇后不在同一列;要保证任意两个皇后不在同一斜线,只需要在递归时判断该行的皇后在排列后前面已经确定位置的皇后是否有处于同一斜线的即可(处于同一斜线的判断方法|行号i-行号j|==|列号i-列号j|)。
每一个皇后的位置按(x,y)格式输出,x表示行号,y表示列号。
#include <iostream>
#include <cmath>
using namespace std;
int n; //皇后个数
int *x; //保存列的值
int count=0; //解法个数
//交换两个数
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
//任意两个皇后不能在斜对面
bool Check(int i)
{
for(int j=1;j<i;j++)
{
if(abs(i-j) == abs(x[i] - x[j]))
{
return false;
}
}
return true;
}
//输出解法
void output(int *x)
{
cout << "解法" << ++count << endl;
for(int j=1;j<=n;j++)
{
cout << "(" << j << ", " << x[j] << ")\t";
}
cout << endl;
}
//求解n皇后问题,不同行要求用循环条件控制,不同列要求用保存列值的数组控制
//该问题只需要在n个列的全排列中剔除出在同一斜线的即可
void Queue(int i)
{
if(i>n)
output(x);
else {
for(int j=i;j<=n;j++)
{
swap(x[i], x[j]);
if(Check(i))
Queue(i+1);
swap(x[i], x[j]);
}
}
}
int main()
{
cout << "input n: ";
cin >> n;
x = new int[n+1];
for(int i=0;i<=n;i++)
{
x[i] = i;
}
Queue(1);
return 0;
}
运行结果: