题目:827. 最大人工岛 困难
思路
(1) 用深度优先搜索遍历每一个岛,统计它们的面积;
(2) 遍历每一块海洋地块,往周边探索,如果探索到陆地,标记上已探索,加上该地块所在岛屿面积,统计累计面积的最大值;
用到的数据结构有:
unordered_map
, unordered_set
新手别混淆了;
代码
class Solution
{
private:
int dir[4][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
int count_S = 0; // 统计每个岛屿的面积
bool isAllLand = true;
int result = 0;
void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y, int mark)
{
int i, j;
int m = grid.size(), n = grid[0].size();
int next_x, next_y;
for (i = 0; i < 4; i++)
{
next_x = x + dir[i][0];
next_y = y + dir[i][1];
if (next_x < 0 || next_x >= m || next_y < 0 || next_y >= n)
{
continue;
}
if (grid[next_x][next_y] == 0)
{
isAllLand = false;
}
if (!visited[next_x][next_y] && grid[next_x][next_y] == 1)
{
count_S++;
visited[next_x][next_y] = true;
grid[next_x][next_y] = mark;
dfs(grid, visited, next_x, next_y, mark);
}
}
}
public:
int largestIsland(vector<vector<int>>& grid)
{
int i, j, k;
int m = grid.size(), n = grid[0].size();
int mark = 1; // 因为地图上已经有了`0,1`
unordered_map<int, int> islandNum; // 编号 -> 面积
vector<vector<bool>> visited(m, vector<bool>(n, 0));
unordered_set<int> visited_island; // 标记访问过的岛屿
int count_S_all = 0; // 记录连接之后的岛屿面积
int near_i, near_j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (grid[i][j] == 0)
{
isAllLand = false;
}
if (!visited[i][j] && grid[i][j] == 1)
{
count_S = 1;
visited[i][j] = true;
mark++; // 这样从 2 开始
grid[i][j] = mark;
dfs(grid, visited, i, j, mark);
islandNum[mark] = count_S;
}
}
}
// 如果全是陆地
if (isAllLand)
{
return m * n;
}
// 看不懂,开抄
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (grid[i][j] == 0)
{
// 假设把[i, j]填成陆地
count_S_all = 1;
visited_island.clear();
for (k = 0; k < 4; k++)
{
near_i = i + dir[k][0];
near_j = j + dir[k][1];
if (near_i < 0 || near_i >= m || near_j < 0 || near_j >= n)
{
continue;
}
if (grid[near_i][near_j] == 0)
{
continue;
}
if (visited_island.count(grid[near_i][near_j]))
{
continue;
}
count_S_all += islandNum[grid[near_i][near_j]]; // 把这个[near_i, near_j]所在的岛的面积加起来
visited_island.insert(grid[near_i][near_j]);
}
result = max(result, count_S_all);
}
}
}
// --------------------------------------------------------------------
return result;
}
};
本地调试用
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;
class Solution
{
private:
int dir[4][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
int count_S = 0; // 统计每个岛屿的面积
bool isAllLand = true;
int result = 0;
void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y, int mark)
{
int i, j;
int m = grid.size(), n = grid[0].size();
int next_x, next_y;
for (i = 0; i < 4; i++)
{
next_x = x + dir[i][0];
next_y = y + dir[i][1];
if (next_x < 0 || next_x >= m || next_y < 0 || next_y >= n)
{
continue;
}
if (grid[next_x][next_y] == 0)
{
isAllLand = false;
}
if (!visited[next_x][next_y] && grid[next_x][next_y] == 1)
{
count_S++;
visited[next_x][next_y] = true;
grid[next_x][next_y] = mark;
dfs(grid, visited, next_x, next_y, mark);
}
}
}
public:
int largestIsland(vector<vector<int>>& grid)
{
int i, j, k;
int m = grid.size(), n = grid[0].size();
int mark = 1; // 因为地图上已经有了`0,1`
unordered_map<int, int> islandNum; // 编号 -> 面积
vector<vector<bool>> visited(m, vector<bool>(n, 0));
unordered_set<int> visited_island; // 标记访问过的岛屿
int count_S_all = 0; // 记录连接之后的岛屿面积
int near_i, near_j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (grid[i][j] == 0)
{
isAllLand = false;
}
if (!visited[i][j] && grid[i][j] == 1)
{
count_S = 1;
visited[i][j] = true;
mark++; // 这样从 2 开始
grid[i][j] = mark;
dfs(grid, visited, i, j, mark);
islandNum[mark] = count_S;
}
}
}
// 如果全是陆地
if (isAllLand)
{
return m * n;
}
/**/
cout << "grid : " << endl;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
cout << grid[i][j] << ", ";
}
cout << endl;
}
for (const auto& pair : islandNum)
{
cout << pair.first << " - " << pair.second << ", ";
}
// ------------------------------------------------------
cout << endl;
// 看不懂,开抄
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (grid[i][j] == 0)
{
// 假设把[i, j]填成陆地
count_S_all = 1;
visited_island.clear();
for (k = 0; k < 4; k++)
{
near_i = i + dir[k][0];
near_j = j + dir[k][1];
if (near_i < 0 || near_i >= m || near_j < 0 || near_j >= n)
{
continue;
}
if (grid[near_i][near_j] == 0)
{
continue;
}
if (visited_island.count(grid[near_i][near_j]))
{
continue;
}
count_S_all += islandNum[grid[near_i][near_j]]; // 把这个[near_i, near_j]所在的岛的面积加起来
visited_island.insert(grid[near_i][near_j]);
}
result = max(result, count_S_all);
}
}
}
// --------------------------------------------------------------------
return result;
}
};
int main()
{
/*
vector<vector<int>> input = { {1, 1, 0, 1} ,
{1, 0, 0, 1} ,
{0, 1, 1, 0} ,
{1, 0, 1, 1} };*/
vector<vector<int>> input = { {1, 0},
{0, 1} };
Solution solution;
cout << solution.largestIsland(input) << endl;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件