洛谷刷题日记||基础篇8

#include <iostream>
#include <vector>
using namespace std;int N, M; // N为行数,M为列数
vector<vector<char>> field; // 表示田地的网格,每个元素是'W'或'.'
vector<vector<bool>> visited; // 用来记录网格是否访问过,防止重复计算// 定义8个方向的偏移量,用于DFS时遍历相邻格子
int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1}; // 行方向的变化量
int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1}; // 列方向的变化量// 深度优先搜索函数,用于从一个起点探索整个水坑
void dfs(int x, int y) {// 标记当前位置为已访问visited[x][y] = true;// 遍历8个相邻方向for (int i = 0; i < 8; i++) {int nx = x + dx[i]; // 计算新位置的行号int ny = y + dy[i]; // 计算新位置的列号// 判断新位置是否有效:在边界内,未被访问过,且是水格子if (nx >= 0 && nx < N && ny >= 0 && ny < M && !visited[nx][ny] && field[nx][ny] == 'W') {dfs(nx, ny); // 递归访问新位置}}
}int main() {cin >> N >> M; // 读取网格的行数和列数field.resize(N, vector<char>(M)); // 初始化网格visited.resize(N, vector<bool>(M, false)); // 初始化访问标记数组为false// 输入田地网格数据for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {cin >> field[i][j]; // 读取每个格子的值('W' 或 '.')}}int pondCount = 0; // 统计水坑的数量// 遍历田地中的每个格子for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {// 如果当前格子是水,且未被访问过,则启动一次DFSif (!visited[i][j] && field[i][j] == 'W') {dfs(i, j); // 使用DFS探索整个连通水坑pondCount++; // 每次启动DFS,说明发现了一个新的水坑}}}// 输出水坑的数量cout << pondCount << endl;return 0;
}


 

 

#include <iostream>
#include <vector>
#include <string>
using namespace std;// 定义方向数组 directions,共 8 个方向
// 分别是:右、下、左、上、右下、左下、右上、左上
const int directions[8][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}, // 水平和垂直方向{1, 1}, {1, -1}, {-1, 1}, {-1, -1} // 对角线方向
};// 检查坐标 (x, y) 是否在矩阵范围内
// x 和 y 都必须在 [0, n) 范围内才是有效位置
bool isValid(int x, int y, int n) {return x >= 0 && x < n && y >= 0 && y < n;
}// 在从 (x, y) 开始、沿 (dx, dy) 方向,寻找是否存在目标单词 word
// 如果找到完整的单词,将路径标记在 visited 矩阵中
bool findWord(vector<string>& matrix, vector<vector<bool>>& visited, int x, int y, int dx, int dy, const string& word) {int n = matrix.size(); // 获取矩阵的大小// 遍历目标单词的每个字符for (int i = 0; i < word.size(); i++) {int nx = x + i * dx; // 根据方向计算目标字符的行坐标int ny = y + i * dy; // 根据方向计算目标字符的列坐标// 检查是否越界或字符不匹配if (!isValid(nx, ny, n) || matrix[nx][ny] != word[i]) {return false; // 如果任意一个字符不符合,返回 false}}// 如果找到完整的单词,将路径标记为 truefor (int i = 0; i < word.size(); i++) {int nx = x + i * dx; // 计算路径上的行坐标int ny = y + i * dy; // 计算路径上的列坐标visited[nx][ny] = true; // 标记该位置属于目标单词路径}return true; // 返回 true 表示找到了单词
}int main() {int n;cin >> n; // 输入矩阵的大小 nvector<string> matrix(n); // 定义 n 行字符串组成的矩阵for (int i = 0; i < n; i++) {cin >> matrix[i]; // 输入矩阵的每一行}string target = "yizhong"; // 目标单词int targetLen = target.length(); // 目标单词的长度vector<vector<bool>> visited(n, vector<bool>(n, false)); // 定义标记矩阵,初始化为 false// 遍历矩阵中的每个位置,检查是否能找到 "yizhong"for (int i = 0; i < n; i++) { // 遍历每一行for (int j = 0; j < n; j++) { // 遍历每一列if (matrix[i][j] == 'y') { // 只有起点是 'y' 时,才有可能找到单词for (auto dir : directions) { // 遍历 8 个方向findWord(matrix, visited, i, j, dir[0], dir[1], target);}}}}// 构造输出矩阵,根据 visited 矩阵决定输出内容for (int i = 0; i < n; i++) { // 遍历每一行for (int j = 0; j < n; j++) { // 遍历每一列if (!visited[i][j]) { // 如果该位置不在单词路径中cout << '*'; // 输出 '*'} else { // 如果该位置是单词路径的一部分cout << matrix[i][j]; // 输出原字符}}cout << endl; // 输出换行符,切换到下一行}return 0; // 程序结束,返回 0
}

这段代码的作用是从矩阵中的某个起点 (x, y) 开始,沿指定方向 (dx, dy) 检查能否连续找到目标单词 word。我们逐个字符进行匹配,并确保目标位置有效且字符符合要求。如果任一条件不满足,立即返回 false。下面是对每一部分的详细解释:

 for (int i = 0; i < word.size(); i++) {int nx = x + i * dx; // 根据方向计算目标字符的行坐标int ny = y + i * dy; // 根据方向计算目标字符的列坐标// 检查是否越界或字符不匹配if (!isValid(nx, ny, n) || matrix[nx][ny] != word[i]) {return false; // 如果任意一个字符不符合,返回 false}}

小技巧

  1. 减少重复检查:由于 nxny 的计算是基于线性关系的,可以直接在循环中累计结果。
  2. 提前终止:发现不匹配时立刻返回,节约时间。

这段代码的核心是通过数学计算实现精确的方向定位和单词匹配。


 


 

 

逐步解析

逆向思维

标记外部 0
  1. 遍历矩阵边界的每一行和每一列。
    • 如果某个位置是 0 且未访问过,将其加入队列并标记为已访问。
  2. 利用 BFS,检查所有与当前边界 0 连通的其他 0,标记它们为外部 0
填充闭合圈内的 0
  1. 遍历矩阵中的每个格子。
    • 如果某个位置是 0 且未被标记为外部 0(visited[i][j] == false),说明该格子在闭合圈内。
    • 将该格子的值修改为 2
输出结果
  • 遍历矩阵,逐个输出值,格式化输出。

 

#include <iostream>
#include <vector>
#include <queue>
using namespace std;// 四个方向数组,用于表示上下左右移动的偏移量
const int directions[4][2] = {{0, 1},  // 右{1, 0},  // 下{0, -1}, // 左{-1, 0}  // 上
};// 检查坐标 (x, y) 是否在矩阵范围内
bool isValid(int x, int y, int n) {return x >= 0 && x < n && y >= 0 && y < n;
}// 标记所有与矩阵边界连通的 0
void markOutsideZeroes(vector<vector<int>>& matrix, vector<vector<bool>>& visited) {int n = matrix.size();queue<pair<int, int>> q; // 队列用于 BFS 遍历// 遍历矩阵的四个边界,将边界上的 0 入队for (int i = 0; i < n; i++) {if (matrix[i][0] == 0 && !visited[i][0]) { // 左边界q.push({i, 0});       // 入队visited[i][0] = true; // 标记为已访问}if (matrix[i][n - 1] == 0 && !visited[i][n - 1]) { // 右边界q.push({i, n - 1});visited[i][n - 1] = true;}}for (int j = 0; j < n; j++) {if (matrix[0][j] == 0 && !visited[0][j]) { // 上边界q.push({0, j});visited[0][j] = true;}if (matrix[n - 1][j] == 0 && !visited[n - 1][j]) { // 下边界q.push({n - 1, j});visited[n - 1][j] = true;}}// 使用 BFS 遍历所有与边界连通的 0while (!q.empty()) {auto [x, y] = q.front(); // 取出队首元素q.pop();// 遍历当前点的上下左右四个方向for (auto dir : directions) {int nx = x + dir[0]; // 计算新坐标int ny = y + dir[1];// 如果新坐标有效且是未访问的 0,则将其入队if (isValid(nx, ny, n) && matrix[nx][ny] == 0 && !visited[nx][ny]) {visited[nx][ny] = true; // 标记为已访问q.push({nx, ny});       // 入队}}}
}// 将闭合圈内的 0 填充为 2
void fillInnerZeroes(vector<vector<int>>& matrix, const vector<vector<bool>>& visited) {int n = matrix.size();for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {// 如果当前格子是 0 且未被标记为外部 0if (matrix[i][j] == 0 && !visited[i][j]) {matrix[i][j] = 2; // 填充为 2}}}
}int main() {int n;cin >> n; // 输入矩阵大小vector<vector<int>> matrix(n, vector<int>(n)); // 定义 n x n 的矩阵vector<vector<bool>> visited(n, vector<bool>(n, false)); // 标记矩阵,用于记录外部 0 是否已访问// 输入矩阵for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {cin >> matrix[i][j]; // 逐个读取矩阵元素}}// 第一步:标记所有与边界连通的 0markOutsideZeroes(matrix, visited);// 第二步:将闭合圈内的 0 填充为 2fillInnerZeroes(matrix, visited);// 输出结果矩阵for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {cout << matrix[i][j] << " "; // 输出矩阵元素}cout << endl; // 每行结束后换行}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/61020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

随机森林(Random Forest, RF)筛选回归数据(处理异常值)

下面是一个完整的 MATLAB 代码示例&#xff0c;用于实现随机森林&#xff08;Random Forest, RF&#xff09;回归&#xff0c;执行 5 折交叉验证&#xff0c;并根据预测误差删除误差较大的行&#xff0c;将处理后的数据保存为新的 Excel 文件。 % 导入数据 data readmatrix(d…

Qwen2.5-3B-Instruct-GGUF部署

注册账号&#xff1a; 魔搭社区 等一会&#xff1a; 部署好了&#xff1a; 立即使用&#xff1a; 您部署的服务提供OpenAI API接口&#xff0c;可通过OpenAI SDK进行调用。请确保您的服务处于正常运行状态&#xff0c;并预先安装OpenAI SDK: pip install openai 在本地新建…

微信小程序进行md5加密 ,base64 转码

封装一个Md5加密的工具 &#xff1a; utils /md5.js function md5(string) { function md5_RotateLeft(lValue, iShiftBits) { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); } function md5_AddUnsigned(lX, lY) { var lX4, lY4, l…

服务器虚拟化技术深度解析及代码应用案例

服务器虚拟化技术深度解析及代码应用案例 在现代数据中心和云计算环境中&#xff0c;服务器虚拟化技术已经成为提高资源利用率、降低成本和简化管理的重要手段。本文将详细介绍服务器虚拟化的基本概念、主要类型、技术特性、应用优势&#xff0c;并通过一个基于Golang的容器化…

深入解析Python中的逻辑回归:从入门到精通

引言 在数据科学领域&#xff0c;逻辑回归&#xff08;Logistic Regression&#xff09;是一个非常重要的算法&#xff0c;它不仅用于二分类问题&#xff0c;还可以通过一些技巧扩展到多分类问题。逻辑回归因其简单、高效且易于解释的特点&#xff0c;在金融、医疗、广告等多个…

恶意PDF文档分析记录

0x1 PDF是什么 PDF&#xff08;便携式文件格式&#xff0c;Portable Document Format&#xff09;是由Adobe Systems在1993年用於文件交换所发展出的文件格式。 因为PDF的文件格式性质广泛用于商业办公&#xff0c;引起众多攻击者对其开展技术研究&#xff0c;在一些APT&#…

Spring-事务学习

spring事务 1. 什么是事务? 事务其实是一个并发控制单位&#xff0c;是用户定义的一个操作序列&#xff0c;这些操作要么全部完成&#xff0c;要不全部不完成&#xff0c;是一个不可分割的工作单位。事务有 ACID 四个特性&#xff0c;即&#xff1a; 原子性&#xff08;Atom…

CVE-2024-2961漏洞的简单学习

简单介绍 PHP利用glibc iconv()中的一个缓冲区溢出漏洞&#xff0c;实现将文件读取提升为任意命令执行漏洞 在php读取文件的时候可以使用 php://filter伪协议利用 iconv 函数, 从而可以利用该漏洞进行 RCE 漏洞的利用场景 PHP的所有标准文件读取操作都受到了影响&#xff1…

[Kotlin标准函数] run、with、apply、also、let、use等

文章目录 1. let2. with2.1 参数解析2.2 用法示例 3、use函数 1. let 2. with 2.1 参数解析 第一个参数可以是一个任意类型的对象&#xff0c; 第二个参数是一个Lambda表达式 with函数会在Lambda表达式中提供第一个参数对象的上下文&#xff0c; 并使用Lambda表达式中的最后…

2024山西省网络建设运维第十八届职业院校技能大赛解析答案(3. ansible 服务)

\3. ansible 服务 任务描述:请采用ansible,实现自动化运维。 (1)在Server2上安装系统自带的ansible-core,作为ansible 控制节 点。Linux1-linux7 作为 ansible 的受控节点。 (2)编写/root/resolv.yml 剧本,实现在所有linux主机的 /etc/resolv.conf文件,文件内容均…

PageOffice打开保存文件的执行流程(工作原理)

一、PageOffice打开文件 触发PageOffiice弹窗&#xff1a;在想要打开Office文件的页面上&#xff0c;通过点击按钮或链接来调用POBrowser.openWindow() 方法&#xff0c;此时会弹出一个PageOffice浏览器窗口&#xff0c;这个窗口中会自动加载openWindow()方法的第一个参数指向…

【FFmpeg系列】:音频处理

前言 在多媒体处理领域&#xff0c;FFmpeg无疑是一个不可或缺的利器。它功能强大且高度灵活&#xff0c;能够轻松应对各种音频和视频处理任务&#xff0c;无论是简单的格式转换&#xff0c;还是复杂的音频编辑&#xff0c;都不在话下。然而&#xff0c;要想真正发挥FFmpeg的潜…

段探测的研究

在介绍今天的内容之前&#xff0c;我们先要知道一些前置的知识 跳过繁琐的介绍&#xff0c;我们单刀直入&#xff0c;介绍一个划时代的CPU 8086 8086 从8086开始&#xff0c;CPU扩展到了16位&#xff0c;地址的位宽扩展到了20位&#xff0c;自此之后我们现在所熟知的计算机结…

pytorch环境问题以及探索Dataloader的数据格式

1 问题 DataLoader object is not subscriptable No module named matplotlib/torchvision.io 2 方法 针对问题一&#xff1a;“dataloader” object is not subscriptable 是一个 Python 中常见的错误。它通常是由于对 dataloader 取下标而导致的。 在 PyTorch 中&#xff0c;…

Linux:进程的优先级 进程切换

文章目录 前言一、进程优先级1.1 基本概念1.2 查看系统进程1.3 PRI和NI1.4 调整优先级1.4.1 top命令1.4.2 nice命令1.4.3 renice命令 二、进程切换2.1 补充概念2.2 进程的运行和切换步骤&#xff08;重要&#xff09; 二、Linux2.6内核进程O(1)调度队列&#xff08;重要&#x…

【学习心得】算力云平台上的大模型部署并实现远程调用

以AutoDL算力云平台为例&#xff0c;部署国产开源ChatGLM3b模型。 一、准备工作 &#xff08;1&#xff09;准备一台算力服务器 首先&#xff0c;进入AutoDL官网的算力时长选择算力服务器资源。 创建好后会自动跳转控制台的“容器实例”界面&#xff0c;稍等片刻后选择“快捷…

【Linux】—进程地址空间

大家好呀&#xff0c;我是残念&#xff0c;希望在你看完之后&#xff0c;能对你有所帮助&#xff0c;有什么不足请指正&#xff01;共同学习交流哦 本文由&#xff1a;残念ing原创CSDN首发&#xff0c;如需要转载请通知 个人主页&#xff1a;残念ing-CSDN博客&#xff0c;欢迎各…

leetcode-44-通配符匹配

题解&#xff1a; 代码&#xff1a; 参考&#xff1a; (1)牛客华为机试HJ71字符串通配符 (2)leetcode-10-正则表达式匹配

【redis】redis

1.linux离线安装 解压 redis-6.2.6.tar.gz进入redis-6.2.6执行make编译执行./make install PREFIX/app/soft/redis6安装 2. 使用客户端 redis-cli 启动默认6379 redis-cli -p port指定端口 -h ip -n 仓库号 【redis-cli -p 6379 -h 192.168.23.22】 auth username#passwd 或…

低成本出租屋5G CPE解决方案:ZX7981PG/ZX7981PM WIFI6千兆高速网络

刚搬进新租的房子&#xff0c;没有网络&#xff0c;开个热点&#xff1f;续航不太行。随身WIFI&#xff1f;大多是百兆级网络。找人拉宽带&#xff1f;太麻烦&#xff0c;退租的时候也不能带着走。5G CPE倒是个不错的选择&#xff0c;插入SIM卡就能直接连接5G网络&#xff0c;千…