前言
蓝桥杯2021年模拟赛,编程题(C++)
N皇后问题是非常经典的问题,也是考察的重点
一、题目描述
有一个 n×n 的国际象棋棋盘(n 行 n 列的方格图),请在棋盘中摆放 n 个受伤的国际象棋皇后,要求:
- 任何两个皇后不在同一行。
- 任何两个皇后不在同一列。
- 如果两个皇后在同一条 45 度角的斜线上,这两个皇后之间行号的差值至少为 3 。
请问一共有多少种摆放方案。
输入描述
输入的第一行包含一个整数 n。
其中,1≤n≤10。
输出描述
输出一个整数,表示答案。
输入输出样例
示例 1
输入
4
输出
2
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
二、思路
这个题目与以往的N皇后题目有一个细微的差别,经典的N皇后问题是皇后不能放置在45度的斜线上,而本题目允许行数大于等于3的皇后放到45度的斜线上。
数据结构上,尝试用col[i]=j 这个数组表示在第i行第j列放有棋子,比二维数组更节约空间。
算法上,DFS(int r)表示当前遍历的行数为r,也就是当前行判断该列是否能放,能放就递归调用DFS(r+1),另外一个非常重要的check(int c,int r) 函数,用来检测当前第r行第c列如果放置棋子是否冲突,冲突判断的条件是行不能重复,列不能重复,同时对角线不能重复,也就是
abs(i-r)!=abs(c-col[i])&&abs(i-r)>=3 //其中i是循环遍历行的参数
三、具体代码
#include<bits/stdc++.h>
using namespace std;
int col[15]={0}; //存储第i行的列信息
int tot=0;
int n;
//int ans[15]={0};
bool check(int c,int r)
{
for(int i=0;i<r;i++) //遍历行
{
if(col[i]==c) //代表前面的行已经在该列存放
{
return false;
}
else if(abs(i-r)==abs(col[i]-c)&&abs(i-r)<3) //放到了对角线上,非法
{
return false;
}
}
return true;
}
void dfs(int r)
{
if(r==n)
{
tot++;
return;
}
for(int i=0;i<n;i++)
{
if(check(i,r))
{
col[r]=i;
dfs(r+1);
}
}
}
int main()
{
cin>>n;
dfs(0);
cout<<tot<<endl;
return 0;
}