C++课后习题训练记录Day120

1.练习项目:

问题描述

给定一个 n×n 的棋盘。现在要向棋盘中放入 n 个黑皇后和 n 个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。

问总共有多少种放法?

输入格式

输入的第一行包含一个整数 n。

输出格式

输出一行包含一个整数,表示答案。

2.选择课程

在蓝桥云课中选择题库,选择题号17013并开始练习。

3.开始练习

(1)源码 :

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N=15;

ll n,ans;

ll vis_b[N][N],vis_w[N][N];

bool pos[N][N];

void dfs_w(int dep)

{

if(dep==n+1){

ans++;

return;

}

for(int i=1;i<=n;i++){

if(vis_w[dep][i])continue;

if(pos[dep][i])continue;

for(int j=1;j<=n;j++)vis_w[j][i]++;

for(int k=i,t=dep;k<=n&&t<=n;k++,t++)vis_w[t][k]++;

for(int k=i,t=dep;k>=1&&t>=1;k--,t--)vis_w[t][k]++;

for(int k=i,t=dep;k<=n&&t>=1;k++,t--)vis_w[t][k]++;

for(int k=i,t=dep;k>=1&&t<=n;k--,t++)vis_w[t][k]++;

dfs_w(dep+1);

for(int j=1;j<=n;j++)vis_w[j][i]--;

for(int k=i,t=dep;k<=n&&t<=n;k++,t++)vis_w[t][k]--;

for(int k=i,t=dep;k>=1&&t>=1;k--,t--)vis_w[t][k]--;

for(int k=i,t=dep;k<=n&&t>=1;k++,t--)vis_w[t][k]--;

for(int k=i,t=dep;k>=1&&t<=n;k--,t++)vis_w[t][k]--;

}

}

void dfs_b(int dep) {

if(dep == n+1) {

dfs_w(1);

return;

}

for(int i = 1; i <= n; i++) {

if(vis_b[dep][i]) continue;

pos[dep][i] = true;

for(int j = 1; j <= n; j++)vis_b[dep][j]++,vis_b[j][i]++;

for(int k=i,t=dep; k<=n&&t<=n; k++,t++) vis_b[t][k]++;

for(int k=i,t=dep; k>=1&&t>=1; k--,t--) vis_b[t][k]++;

for(int k=i,t=dep; k<=n&&t>=1; k++,t--) vis_b[t][k]++;

for(int k=i,t=dep; k>=1&&t<=n; k--,t++) vis_b[t][k]++;

dfs_b(dep + 1);

pos[dep][i] = false;

for(int j = 1; j <= n; j++)vis_b[dep][j]--,vis_b[j][i]--;

for(int k=i,t=dep; k<=n&&t<=n; k++,t++) vis_b[t][k]--;

for(int k=i,t=dep; k>=1&&t>=1; k--,t--) vis_b[t][k]--;

for(int k=i,t=dep; k<=n&&t>=1; k++,t--) vis_b[t][k]--;

for(int k=i,t=dep; k>=1&&t<=n; k--,t++) vis_b[t][k]--;

}

}

int main()

{

ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);

cin>>n;

dfs_b(1);

cout<<ans<<'\n';

return 0;

}

(2)检验结果

对此代码进行检验,检验后无报错,提交此代码,判题结果为正确90分,发现最后一个案例超时,对源代码进行优化,优化过后的代码如下:

#include<bits/stdc++.h>

using namespace std;

const int N = 15;

int n, cnt = 0; // cnt: 单色皇后解的数量

int pos[3000][N]; // pos[k][i] 表示第k个解中第i行皇后所在的列

int vis[N][N]; // 攻击标记

int loc[N]; // 当前解的各行皇后列位置

void dfs(int dep) {

if (dep == n + 1) {

cnt++;

for (int i = 1; i <= n; i++)

pos[cnt][i] = loc[i];

return;

}

for (int i = 1; i <= n; i++) {

if (vis[dep][i]) continue;

loc[dep] = i;

// 标记攻击范围(保留你熟悉的二维标记方式)

for (int j = 1; j <= n; j++) vis[dep][j]++, vis[j][i]++;

for (int k = i, t = dep; k <= n && t <= n; k++, t++) vis[t][k]++;

for (int k = i, t = dep; k >= 1 && t >= 1; k--, t--) vis[t][k]++;

for (int k = i, t = dep; k <= n && t >= 1; k++, t--) vis[t][k]++;

for (int k = i, t = dep; k >= 1 && t <= n; k--, t++) vis[t][k]++;

dfs(dep + 1);

// 回溯

for (int j = 1; j <= n; j++) vis[dep][j]--, vis[j][i]--;

for (int k = i, t = dep; k <= n && t <= n; k++, t++) vis[t][k]--;

for (int k = i, t = dep; k >= 1 && t >= 1; k--, t--) vis[t][k]--;

for (int k = i, t = dep; k <= n && t >= 1; k++, t--) vis[t][k]--;

for (int k = i, t = dep; k >= 1 && t <= n; k--, t++) vis[t][k]--;

}

}

int main() {

ios::sync_with_stdio(false); cin.tie(0);

cin >> n;

dfs(1);

int ans = 0;

for (int i = 1; i <= cnt; i++) { // 枚举黑皇后解

for (int j = 1; j <= cnt; j++) { // 枚举白皇后解

bool ok = true;

for (int r = 1; r <= n; r++) { // 检查每一行是否同列(同格)

if (pos[i][r] == pos[j][r]) {

ok = false;

break;

}

}

if (ok) ans++;

}

}

cout << ans << '\n';

return 0;

}

对此代码进行检验,检验后无报错,提交此代码,判题结果为正确100分。

(3)练习心得:注意每段代码末尾的分号是否存在,如不存在则需即使补充;输入法是否切换 为英语模式;语法是否错误。

相关推荐
我还记得那天几秒前
C语言递归实现汉诺塔问题
c语言·开发语言
不吃土豆的马铃薯2 分钟前
Spdlog 入门:日志记录器与日志槽基础详解
服务器·开发语言·c++·c·日志·spdlog
此生决int6 分钟前
算法从入门到精通——前缀和
c++·算法·蓝桥杯
凯瑟琳.奥古斯特11 分钟前
传输层核心功能解析
开发语言·网络·职场和发展
Fuyo_111926 分钟前
C++中的活字印刷术——模板·初阶
开发语言·c++·笔记
小白|27 分钟前
cmake:昇腾CANN构建系统完全指南
java·c++·算法
在角落发呆27 分钟前
跨越网络鸿沟:传统文件传输与现代内网穿透的奇妙交响
开发语言·php
王老师青少年编程28 分钟前
2026年全国青少年信息素养大赛“算法应用主题赛”(初赛)【C++考点大纲】(全场景、组别):文末附备考秘籍!
c++·全国青少年信息素养大赛·初赛·2026年·算法应用主题赛·考点大纲
Season45031 分钟前
C++之模板元编程(前置知识 constexpr)
开发语言·c++
AI玫瑰助手33 分钟前
Python运算符:比较运算符(等于不等等于大于小于)与返回值
android·开发语言·python