当前位置: 首页 > news >正文

【c++刷题笔记-图论】day52: 101.孤岛的总面积 、102.沉没孤岛 、103.水流问题 、104.建造最大岛屿

101. 孤岛的总面积

思路:将所有靠近陆地的1全部置为0,然后统计没有变为0的1的个数

重点:从四条边边缘开始遍历

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
void bfs(vector<vector<int>>& grid, int x, int y) {queue<pair<int, int>> que;que.push({x, y});grid[x][y] = 0; // 只要加入队列,立刻标记while(!que.empty()) {pair<int ,int> cur = que.front(); que.pop();int curx = cur.first;int cury = cur.second;for (int i = 0; i < 4; i++) {int nextx = curx + dir[i][0];int nexty = cury + dir[i][1];if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 越界了,直接跳过if (grid[nextx][nexty] == 1) {que.push({nextx, nexty});grid[nextx][nexty] = 0; // 只要加入队列立刻标记}}}
}int main() {int n, m;cin >> n >> m;vector<vector<int>> grid(n, vector<int>(m, 0));for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {cin >> grid[i][j];}}// 从左侧边,和右侧边 向中间遍历for (int i = 0; i < n; i++) {if (grid[i][0] == 1) bfs(grid, i, 0);if (grid[i][m - 1] == 1) bfs(grid, i, m - 1);}// 从上边和下边 向中间遍历for (int j = 0; j < m; j++) {if (grid[0][j] == 1) bfs(grid, 0, j);if (grid[n - 1][j] == 1) bfs(grid, n - 1, j);}int count = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 1) count++;}}cout << count << endl;
}

102. 沉没孤岛

思路:把所有靠近陆地的1变成2。然后将所有1变成0,再将所有2变成1

#include <iostream>
#include <vector>
using namespace std;
int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1}; // 保存四个方向
void dfs(vector<vector<int>>& grid, int x, int y) {grid[x][y] = 2;for (int i = 0; i < 4; i++) { // 向四个方向遍历int nextx = x + dir[i][0];int nexty = y + dir[i][1];// 超过边界if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;// 不符合条件,不继续遍历if (grid[nextx][nexty] == 0 || grid[nextx][nexty] == 2) continue;dfs (grid, nextx, nexty);}return;
}int main() {int n, m;cin >> n >> m;vector<vector<int>> grid(n, vector<int>(m, 0));for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {cin >> grid[i][j];}}// 步骤一:// 从左侧边,和右侧边 向中间遍历for (int i = 0; i < n; i++) {if (grid[i][0] == 1) dfs(grid, i, 0);if (grid[i][m - 1] == 1) dfs(grid, i, m - 1);}// 从上边和下边 向中间遍历for (int j = 0; j < m; j++) {if (grid[0][j] == 1) dfs(grid, 0, j);if (grid[n - 1][j] == 1) dfs(grid, n - 1, j);}// 步骤二、步骤三for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 1) grid[i][j] = 0;if (grid[i][j] == 2) grid[i][j] = 1;cout << grid[i][j] << " ";}cout << endl;}
}

 103. 水流问题

思路:从底向上,逆流而上。从两个边界向上遍历,统计是否遍历过。然后判断如果两个方向都遍历过就是答案

#include <iostream>
#include <vector>
using namespace std;
int n, m;
int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1};
void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y) {if (visited[x][y]) return;visited[x][y] = true;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= n || nexty < 0 || nexty >= m) continue;if (grid[x][y] > grid[nextx][nexty]) continue; // 注意:这里是从低向高遍历dfs (grid, visited, nextx, nexty);}return;
}int main() {cin >> n >> m;vector<vector<int>> grid(n, vector<int>(m, 0));for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {cin >> grid[i][j];}}// 标记从第一组边界上的节点出发,可以遍历的节点vector<vector<bool>> firstBorder(n, vector<bool>(m, false));// 标记从第一组边界上的节点出发,可以遍历的节点vector<vector<bool>> secondBorder(n, vector<bool>(m, false));// 从最上和最下行的节点出发,向高处遍历for (int i = 0; i < n; i++) {dfs (grid, firstBorder, i, 0); // 遍历最左列,接触第一组边界dfs (grid, secondBorder, i, m - 1); // 遍历最右列,接触第二组边界}// 从最左和最右列的节点出发,向高处遍历for (int j = 0; j < m; j++) {dfs (grid, firstBorder, 0, j); // 遍历最上行,接触第一组边界dfs (grid, secondBorder, n - 1, j); // 遍历最下行,接触第二组边界}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {// 如果这个节点,从第一组边界和第二组边界出发都遍历过,就是结果if (firstBorder[i][j] && secondBorder[i][j]) cout << i << " " << j << endl;;}}}

104. 建造最大岛屿 (kamacoder.com)

思路:使用map记录每个岛屿的最大面积,key是编号,value是最大面积。然后遍历尝试0变成1返回最大的面积

#include <iostream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
using namespace std;
int n, m;
int count;int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y, int mark) {if (visited[x][y] || grid[x][y] == 0) return; // 终止条件:访问过的节点 或者 遇到海水visited[x][y] = true; // 标记访问过grid[x][y] = mark; // 给陆地标记新标签count++;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= n || nexty < 0 || nexty >= m) continue;  // 越界了,直接跳过dfs(grid, visited, nextx, nexty, mark);}
}int main() {cin >> n >> m;vector<vector<int>> grid(n, vector<int>(m, 0));for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {cin >> grid[i][j];}}vector<vector<bool>> visited(n, vector<bool>(m, false)); // 标记访问过的点unordered_map<int ,int> gridNum;int mark = 2; // 记录每个岛屿的编号bool isAllGrid = true; // 标记是否整个地图都是陆地for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 0) isAllGrid = false;if (!visited[i][j] && grid[i][j] == 1) {count = 0;dfs(grid, visited, i, j, mark); // 将与其链接的陆地都标记上 truegridNum[mark] = count; // 记录每一个岛屿的面积mark++; // 记录下一个岛屿编号}}}if (isAllGrid) {cout << n * m << endl; // 如果都是陆地,返回全面积return 0; // 结束程序}// 以下逻辑是根据添加陆地的位置,计算周边岛屿面积之和int result = 0; // 记录最后结果unordered_set<int> visitedGrid; // 标记访问过的岛屿for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {count = 1; // 记录连接之后的岛屿数量visitedGrid.clear(); // 每次使用时,清空if (grid[i][j] == 0) {for (int k = 0; k < 4; k++) {int neari = i + dir[k][1]; // 计算相邻坐标int nearj = j + dir[k][0];if (neari < 0 || neari >= n || nearj < 0 || nearj >= m) continue;if (visitedGrid.count(grid[neari][nearj])) continue; // 添加过的岛屿不要重复添加// 把相邻四面的岛屿数量加起来count += gridNum[grid[neari][nearj]];visitedGrid.insert(grid[neari][nearj]); // 标记该岛屿已经添加过}}result = max(result, count);}}cout << result << endl;}

总结

使用dfs或者bfs模板,再找规律,从四边开始遍历和整体替换值、使用map存岛屿的面积

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C# 多线程Paralle使用
  • LangChain4j-RAG高级-核心概念
  • 区块链——代码格式检查(prettier、solhint)
  • OD C卷 - 密码输入检测
  • Linux操作系统 -socket网络通信
  • 深入理解计算机系统 CSAPP 家庭作业11.10
  • 【资料分享】2024钉钉杯大数据挑战赛A题思路解析+代码演示
  • vue 当前页面刷新 provide + inject
  • pytorch backbone
  • 代理协议解析:如何根据需求选择HTTP、HTTPS或SOCKS5?
  • Win11+Anaconda+VScode:mmpose环境配置与基本使用
  • Springboot @Validate @Valid 基于复杂嵌套对象的参数校验示例
  • SQL 基础知识
  • Springboot 多数据源事务
  • 代码随想录算法训练营day22 | 77. 组合、216.组合总和III 、17.电话号码的字母组合
  • hexo+github搭建个人博客
  • 2017-08-04 前端日报
  • Facebook AccountKit 接入的坑点
  • Javascript基础之Array数组API
  • js ES6 求数组的交集,并集,还有差集
  • Js基础知识(四) - js运行原理与机制
  • leetcode讲解--894. All Possible Full Binary Trees
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • node入门
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 后端_MYSQL
  • 如何在GitHub上创建个人博客
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 使用API自动生成工具优化前端工作流
  • 收藏好这篇,别再只说“数据劫持”了
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 怎样选择前端框架
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 回归生活:清理微信公众号
  • 积累各种好的链接
  • !!java web学习笔记(一到五)
  • ###STL(标准模板库)
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (day 12)JavaScript学习笔记(数组3)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (二)windows配置JDK环境
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
  • (南京观海微电子)——示波器使用介绍
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • ****三次握手和四次挥手
  • *p++,*(p++),*++p,(*p)++区别?
  • *算法训练(leetcode)第四十天 | 647. 回文子串、516. 最长回文子序列
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .net core 依赖注入的基本用发
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • .set 数据导入matlab,设置变量导入选项 - MATLAB setvaropts - MathWorks 中国