这类问题一直做的不好,岛屿问题是一个系列问题。以下题目来自力扣。
L200. 岛屿数量 (Easy)
463. 岛屿的周长 (Easy)
695. 岛屿的最大面积 (Medium)
827. 最大人工岛 (Hard)
1、 岛屿数量
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
class Solution { private: void dfs(vector<vector<char>>& grid, int r, int c) { int nr = grid.size(); int nc = grid[0].size(); grid[r][c] = '0'; if (r - 1 >= 0 && grid[r-1][c] == '1') dfs(grid, r - 1, c); if (r + 1 < nr && grid[r+1][c] == '1') dfs(grid, r + 1, c); if (c - 1 >= 0 && grid[r][c-1] == '1') dfs(grid, r, c - 1); if (c + 1 < nc && grid[r][c+1] == '1') dfs(grid, r, c + 1); } public: int numIslands(vector<vector<char>>& grid) { int nr = grid.size(); if (!nr) return 0; int nc = grid[0].size(); int num_islands = 0; for (int r = 0; r < nr; ++r) { for (int c = 0; c < nc; ++c) { if (grid[r][c] == '1') { ++num_islands; dfs(grid, r, c); } } } return num_islands; } };
2、 岛屿的周长
给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域。
网格中的格子水平和垂直方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。
class Solution { public: int islandPerimeter(vector<vector<int>>& grid) { for (int r = 0; r < grid.size(); r++) { for (int c = 0; c < grid[0].size(); c++) { if (grid[r][c] == 1) { return area(grid, r, c); } } } return 0; } int area(vector<vector<int>>& grid, int r, int c) { if (!(0 <= r && r < grid.size() && 0 <= c && c < grid[0].size())) { return 1; } if (grid[r][c] == 0) { return 1; } if (grid[r][c] != 1) { return 0; } grid[r][c] = 2; return area(grid, r - 1, c) + area(grid, r + 1, c) + area(grid, r, c - 1) + area(grid, r, c + 1); } };
3、岛屿的最大面积
一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)
class Solution { public: int maxAreaOfIsland(vector<vector<int>>& grid) { if (grid.empty() || grid[0].empty()) { return 0; } int res = 0; for (int r = 0; r < grid.size(); r++) { for (int c = 0; c < grid[0].size(); c++) { if (grid[r][c] == 1) { int a = area(grid, r, c); res = max(res, a); } } } return res; } int area(vector<vector<int>>& grid, int r, int c) { if (!(0 <= r && r < grid.size() && 0 <= c && c < grid[0].size())) { return 0; } if (grid[r][c] != 1) { return 0; } grid[r][c] = 2; return 1 + area(grid, r - 1, c) + area(grid, r + 1, c) + area(grid, r, c - 1) + area(grid, r, c + 1); } };
4、迷宫问题
牛客上的一道迷宫问题。
定义一个二维数组N*M。它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。入口点为[0,0],既第一空格是可以走的路。
感觉讨论区的解法不错,记录学习
#include<iostream> #include<vector> using namespace std; int N, M; //分别代表行和列 vector<vector<int>> maze;//迷宫矩阵 vector<vector<int>> path_temp;//存储当前路径,第一维表示位置 vector<vector<int>> path_best;//存储最佳路径 void MazeTrack(int i, int j) { maze[i][j] = 1;//表示当前节点已走,不可再走 path_temp.push_back({ i, j });//将当前节点加入到路径中 if (i == N - 1 && j == M - 1) //判断是否到达终点 if (path_best.empty() || path_temp.size() < path_best.size()) path_best = path_temp; if (i - 1 >= 0 && maze[i - 1][j] == 0)//探索向上走是否可行 MazeTrack(i - 1, j); if (i + 1 < N && maze[i + 1][j] == 0)//探索向下走是否可行 MazeTrack(i + 1, j); if (j - 1 >= 0 && maze[i][j - 1] == 0)//探索向左走是否可行 MazeTrack(i, j - 1); if (j + 1 < M && maze[i][j + 1] == 0)//探索向右走是否可行 MazeTrack(i, j + 1); maze[i][j] = 0; //恢复现场,设为未走 path_temp.pop_back(); } int main() { while (cin >> N >> M) { maze = vector<vector<int>>(N, vector<int>(M, 0)); path_temp.clear(); path_best.clear(); /*for (auto &i : maze) for (auto &j : i) cin >> j;*/ for(int i =0; i<N; i++){ for(int j =0; j<M; j++){ cin >> maze[i][j]; } } MazeTrack(0, 0);//回溯寻找迷宫最短通路 for (auto i : path_best) cout << '(' << i[0] << ',' << i[1] << ')' << endl;//输出通路 } return 0; }