C++蓝桥杯 基础练习之2n皇后

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(<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值