C++ 蓝桥杯题目讲解汇总(持续更新)
(注:今天摸鱼了,翻来覆去,想了想把n皇后整理一下,毕竟这是第一次实践n皇后问题,还被这题的0卡了一下,导致受题目中的0干扰,😫
VIP试题 2n皇后
资源限制
时间限制:1.0s 内存限制:512.0MB
问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0
思路
总体上的思路是学习八皇后思想,首先完成白皇后的八皇后,再白皇后的基础上完成黑皇后的八皇后情形
对于八皇后棋盘来说:
主对角线共15条,主对角线上的位置满足y-x相等
副对角线共15条,副对角线上的位置满足y+x相等
图片 刘汝佳算法入门经典 P193页 ,书上还有利用位置关系判断冲突的方法
0代表未被占据,1代表占据
v[0][i] 代表第i列是否被占据
v[1][i-cur+n]cur代表行号 代表第i-cur+n条主对角线 实际上是和i对应在一起的左上角
v[2][i+cur]代表第i+cur条副对角线,实际上是和i对应的右上角
实际上V的大小满足v[3][2n-1],2n-1代表的是对角线数
方法就是先获得白皇后满足n皇后情况后的棋盘,
然后在此基础上再去获得黑皇后满足条件的全排列
对于初次接触n皇后的小白来说,需要注意的是:
- 一定要明白n皇后是如何求的
- C[cur]=i 代表的是,C所在的棋盘,第cur行的皇后位置是索引 i
- visit数组是判断皇后位置是否冲突的数组,主要是指同列,同主角线,同副角线,也可以使用其他方法判断,还是根据主角线的y-x和从角线的x+y判定,得到abs(cur-j)==(C[cur]-C[j]),具体的见代码注释
- 当cur从第0行跑到第n-1行,且n-1行成功了,表面进行下一次递归的时候cur==n满足0到n-1行都成立了
- 使用visit辅助数组时候,记得要变回来,给判断下一个列是否填子使用,这里相当于另一种方法的OK=0
- 掌握递归枚举/回溯法
- n皇后的棋盘打印,可以写在n==cur后面,因为此时的C[cur]的n个位置都有着对应的皇后
对于本题来说,需要注意的是:
- 2n皇后的题目中的棋盘有0存在,实际上它是不影响,因为判断来自于visit,它的visit的三个索引只要不是1,就代表列、主角线、从角线到都没有棋子落下,理由就是对角线有15条,每个都是一个独立的结果,不会重复,重复即错误,在0处三者为的话,只是代表这个位置所在的列和对角线都暂时没有棋子,反之则是有棋子,但是不影响流程
- 只要保证在白皇后的时候首先确保白皇后里不会选择输入为0的位置,在黑皇后的位置判断是确保不会选择输入为0和白皇后所在列数即可
- 打印棋盘的方法和n皇后一样的
代码
#include<iostream>
#include<cstring>
#define N 100
using namespace std;
int n;
int ans=0;
int C[N][N]; //C代表输入棋盘,我觉得用到的地方只有那个不能放棋子的0位置
int wvisit[3][N]; // 判断冲突数组
int bvisit[3][N];
int white[N]; //whihe[cur]=j 代表的是第cur行的皇后在j的位置
int black[N];
void white_dfs(<