洛谷刷题日记||基础篇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,一经查实,立即删除!

相关文章

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

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

恶意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…

段探测的研究

在介绍今天的内容之前&#xff0c;我们先要知道一些前置的知识 跳过繁琐的介绍&#xff0c;我们单刀直入&#xff0c;介绍一个划时代的CPU 8086 8086 从8086开始&#xff0c;CPU扩展到了16位&#xff0c;地址的位宽扩展到了20位&#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-正则表达式匹配

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

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

学习日记_20241117_聚类方法(高斯混合模型)

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

列出D3的所有交互方法,并给出示例

D3.js 提供了丰富的交互方法&#xff0c;可以用来增强图表的用户交互体验。以下是一些常用的交互方法及其示例&#xff1a; 1. 鼠标事件 on("mouseover", function) 用途: 当鼠标悬停在元素上时触发。示例:svg.selectAll(".bar").on("mouseover&qu…

设计模式-参考的雷丰阳老师直播课

一般开发中使用的模式为模版模式策略模式组合&#xff0c;模版用来定义骨架&#xff0c;策略用来实现细节。 模版模式 策略模式 与模版模式特别像&#xff0c;模版模式会定义好步骤定义好框架&#xff0c;策略模式定义小细节 入口类 使用模版模式策略模式开发支付 以上使用…

模拟实现STL中的list

目录 1.设计list的结点 2.设计list的迭代器 3.list类的设计总览 4.list类的迭代器操作 5.list类的四个特殊的默认成员函数 无参的默认构造函数 拷贝构造函数 赋值运算符重载函数 析构函数 6.list类的插入操作 7.list类的删除操作 8.list.hpp源代码 1.设计list的结点…

.NET SDK 各操作系统开发环境搭建

一、Win10&#xff08;推荐&#xff09; 1、VS 2022 社区版 # 下载地址 https://visualstudio.microsoft.com/zh-hans/downloads/ 2、.NET 6 SDK # 下载地址 https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0 3、Hello World 如果需要使用旧程序样式时&#xff0c;则…

IDEA怎么定位java类所用maven依赖版本及引用位置

在实际开发中&#xff0c;我们可能会遇到需要搞清楚代码所用依赖版本号及引用位置的场景&#xff0c;便于排查问题&#xff0c;怎么通过IDEA实现呢&#xff1f; 可以在IDEA中打开项目&#xff0c;右键点击maven的pom.xml文件&#xff0c;或者在maven窗口下选中项目&#xff0c;…

【Golang】——Gin 框架中的模板渲染详解

Gin 框架支持动态网页开发&#xff0c;能够通过模板渲染结合数据生成动态页面。在这篇文章中&#xff0c;我们将一步步学习如何在 Gin 框架中配置模板、渲染动态数据&#xff0c;并结合静态资源文件创建一个功能完整的动态网站。 文章目录 1. 什么是模板渲染&#xff1f;1.1 概…

力扣 LeetCode 144. 二叉树的前序遍历(Day6:二叉树)

解题思路&#xff1a; 方法一&#xff1a;递归&#xff08;中左右&#xff09; class Solution {List<Integer> res new ArrayList<>();public List<Integer> preorderTraversal(TreeNode root) {recur(root);return res;}public void recur(TreeNode roo…

高级 SQL 技巧讲解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; SQL&#xff08;结构化查询语言&#xff09;是管理和操作数据库的核心工具。从基本的查询语句到复杂的数据处理&#xff0c;掌握高级 SQL 技巧不仅能显著提高数据分析的效率&#xff0c;还能解决业务中的复…