推荐刷题网站:http://47.108.154.71/http://47.108.154.71/
N皇后问题题目:
在N*N(1<N<=9)的棋盘上放置N个皇后而彼此不受攻击(即在棋盘的任一行,任一列和任一对角线上不能放置2个皇后),编程求解所有的摆放方法。
[输入格式]
一个整数n(1<n<=9)
[输出格式]
若有解,输出若干行,每行n个数,依次表示第i个皇后的列号
若无解,输出 “no”
[输入样例]
4
[输出样例]
2 4 1 3
3 1 4 2
解题思路:
N皇后问题当中有个其妙的规律——各个斜边上的下标差或和相等。
由上图各位读者老爷可以发现斜边上的规律,当然我只列举了其中一条,其实其于斜边都有这种规律,老爷们可以自己去找找。
但是,有没有想过,就这些规律可以有什么作用?
好问题,让我们再回顾一下题目要求即在棋盘的任一行,任一列和任一对角线上不能放置2个皇后
判断任意一行,任意一列和任意对角线上的皇后我们生活中一眼看过去就行了但是,电脑想要识别可不能像我们这样,所以我们找的这个规律就是用来当做行列的“身份证”的。
这样做的目的:通过行,列,对角线上的固定差值,来进行判断记录。
例如黑色线段上的格子,下标的和无论如何都是6。其他的斜边也都有自己一个固定的值,这就像是身份证一样,独一无二,所以判断时,只需判断重复“身份证”没有,即可实现不重复皇后的要求
可问题在于,有些斜边差回事负数,但是C++中下标最下是0,负数是违法的,为了避免这种情况可以统一给所有计算差或和时统一加上N,或者是7,毕竟图最大也就是7,(0,1,2,3,4,5,6,7,八个数)
代码实现
#include <bits/stdc++.h>//万能头文件可概括全部的头文件
using namespace std;
long long sum=0;//sum是拿来计数的所以初始值是0.
bool a[100],c[100],d[100];
int b[100],n;
int print()//这里是定义了一个输出函数
{
sum++;//用来记录方案数量
for(int i=1;i<=n;++i)cout<<b[i]<<" ";//输出当前的全部方案
cout<<endl;//换行
}
int search(int i)
{
for(int j=1;j<=n;++j)
{
if(a[j]==0&&c[i+j]==0&&d[i-j+7]==0)
/*当画一个6*6的格子再根据题目进行分析时可发现:
每行每列每个斜边都有固定的差或者和,可以利用这个进行判断,存进数组
输出回溯……但有些数字差会是负数,且有的行列的差或和会跟其他行列的差或和
重复。所以就将全部数都加上一个7或n,在既保证不是负数
也不重复情况下,又保证每行每列每个斜边上差跟和不一样
这样就十分容易。
注:画图理解更佳*/
{
b[i]=j;//存放 。
a[j]=1;//等于1不再使用 。
c[i+j]=1;
d[i-j+7]=1;
if(i==n)//在满了不再有其他摆放方法时就将当前的方案输出 。
print();
else
search(i+1);
a[j]=0;//回溯 撤回上次的记录 恢复保存结果之前的状态。
c[i+j]=0;//回溯 撤回上次的记录 恢复保存结果之前的状态。
d[i-j+7]=0;//回溯 撤回上次的记录 恢复保存结果之前的状态。
}
}
}
int main()
{
cin>>n;
search(1);
if(sum==0)cout<<"no";//如果无解 一个方案都没有 就按照题目要求输出no。
return 0;
}
游客有好版
#include <bits/stdc++.h>//万能头文件可概括全部的头文件
using namespace std;
long long sum=0;//sum是拿来计数的所以初始值是0.
bool a[100],c[100],d[100];
int b[100],n;
int print()//这里是定义了一个输出函数
{
sum++;//用来记录方案数量
for(int i=1;i<=n;++i)cout<<b[i]<<" ";//输出当前的全部方案
cout<<endl;//换行
}
int search(int i)
{
for(int j=1;j<=n;++j)
{
if(a[j]==0&&c[i+j]==0&&d[i-j+7]==0)
/*当画一个6*6的格子再根据题目进行分析时可发现:
每行每列每个斜边都有固定的差或者和,可以利用这个进行判断,存进数组
输出回溯……但有些数字差会是负数,且有的行列的差或和会跟其他行列的差或和
重复。所以就将全部数都加上一个7或n,在既保证不是负数
也不重复情况下,又保证每行每列每个斜边上差跟和不一样
这样就十分容易。
注:画图理解更佳*/
{
b[i]=j;//存放 。
a[j]=1;//等于1不再使用 。
c[i+j]=1;
d[i-j+7]=1;
if(i==n)//在满了不再有其他摆放方法时就将当前的方案输出 。
print();
else
search(i+1);
a[j]=0;//回溯 撤回上次的记录 恢复保存结果之前的状态。
c[i+j]=0;//回溯 撤回上次的记录 恢复保存结果之前的状态。
d[i-j+7]=0;//回溯 撤回上次的记录 恢复保存结果之前的状态。
}
}
}
int main()
{
cin>>n;
search(1);
if(sum==0)cout<<"no";//如果无解 一个方案都没有 就按照题目要求输出no。
return 0;
}
给个赞吧,谢谢啦…………