一,题目描述
描述
在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。
输入
无输入。
输出
按给定顺序和格式输出所有八皇后问题的解。
二,思路分析
不得不说这道题是真有难度。首先没玩过国际象棋的人连规则都不懂 ,谈何做题?!
所以,让我们康康百度怎么说:
八皇后问题(英文:Eight queens),是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。
(好的谢谢百度登场)
其实这道题是一个回溯的算法,但本人拿函数加递归做的。
题目说不让在同一行或同一列,那我们要么一行一行的找看列,要么一列一列的找看行。
但斜边怎么办?
我们直接上结论:
从左上到右下,行与列之差相等;从右上到左下,行与列之和相等。
大家可以自己根据国际象棋的棋盘去推导,很容易推导出来。
我们定义三个数组,用来标记行,左上到右下和右下到左上三种情况,用来判断是否能落子。
三,递归实现
#include<iostream>
using namespace std;
int o[105][105],l[105],p[105],x[105],sum=1; //所需数组变量全部定义成全局
void fun(int n) //直接输出用void
{
int i,j,k; //只在函数中使用的变量
if(n>8) //程序的边界(递归出口)
{
//开始输出
cout<<"No. "<<sum<<endl;
sum=sum+1; //记录方法数
//二维数组的输出
for(j=1;j<=8;j++)
{
for(k=1;k<=8;k++)
{
cout<<o[j][k]<<" ";
}
cout<<endl;
}
return; /返回上一层
}
for(i=1;i<=8;i++) //一列一列判断行
{
//标记 :l[n]==0是当前行没有被用过,p[n+i]==0是当前从右上到左下的斜边是否被使用过,x[i-n+8]==0当前从左上到右下的斜边是否被使用过
if(l[n]==0&&p[n+i]==0&&x[i-n+8]==0) //加8是因为可能出现负数
{
l[i]=1; //使用后的标记
p[n+i]=1;
x[i-n+8]=1;
o[i][n]=1;
fun(n+1); //本层已找到进入下一层
//还原现场
o[i][n]=0;
l[i]=0;
p[n+i]=0;
x[i-n+8]=0;
}
}
return; //回到上一层
}
int main()
{
fun(1); //主函数中调用
}
#include<iostream>
using namespace std;
int o[105][105],l[105],p[105],x[105],sum=1;
void fun(int n)
{
int i,j,k;
if(n>8)
{
cout<<"No. "<<sum<<endl;
sum=sum+1;
for(j=1;j<=8;j++)
{
for(k=1;k<=8;k++)
{
cout<<o[j][k]<<" ";
}
cout<<endl;
}
return;
}
for(i=1;i<=8;i++)
{
if(l[n]==0&&p[n+i]==0&&x[i-n+8]==0)
{
l[i]=1;
p[n+i]=1;
x[i-n+8]=1;
o[i][n]=1;
fun(n+1);
o[i][n]=0;
l[i]=0;
p[n+i]=0;
x[i-n+8]=0;
}
}
return;
}
int main()
{
fun(1);
}
(92种情况,我就不展示输出结果了,额有点多)
结束!