101. 孤岛的总面积
本题要求不与矩阵边缘相连的孤岛的总面积。先将与四个边缘相连的岛屿变为海洋,再统计剩余的孤岛的总面积。无需再标识访问过的结点,因为访问过后都变为海洋了。
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
DFS
// c++
#include<bits/stdc++.h>
using namespace std;
int direction[4][2] = {0, 1, 0, -1, -1, 0, 1, 0};
int result = 0;
void pre_dfs(vector<vector<int>> &matrix, int x, int y){
matrix[x][y] = 0;
result++;
for(int i=0; i<4; i++){
int nextx = x + direction[i][0];
int nexty = y + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty]){
matrix[nextx][nexty] = 0;
pre_dfs(matrix, nextx, nexty);
}
}
}
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>> matrix(n, vector<int>(m, 0));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>matrix[i][j];
}
}
for(int i=0; i<n; i++) {
if(matrix[i][0]){
pre_dfs(matrix, i, 0);
}
if(matrix[i][m-1]){
pre_dfs(matrix, i, m-1);
}
}
for(int j=0; j<m; j++){
if(matrix[0][j]){
pre_dfs(matrix, 0, j);
}
if(matrix[n-1][j]){
pre_dfs(matrix, n-1, j);
}
}
result = 0;
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(matrix[i][j]){
pre_dfs(matrix, i, j);
}
}
}
cout<<result;
return 0;
}
BFS
// c++
#include<bits/stdc++.h>
using namespace std;
int direction[4][2] = {0, 1, 0, -1, -1, 0, 1, 0};
int result = 0;
void pre_dfs(vector<vector<int>> &matrix, int x, int y){
matrix[x][y] = 0;
result++;
for(int i=0; i<4; i++){
int nextx = x + direction[i][0];
int nexty = y + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty]){
matrix[nextx][nexty] = 0;
pre_dfs(matrix, nextx, nexty);
}
}
}
void pre_bfs(vector<vector<int>> &matrix, int x, int y){
queue<pair<int, int>> que;
que.push({x, y});
matrix[x][y] = 0;
result++;
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 + direction[i][0];
int nexty = cury + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty]){
matrix[nextx][nexty] = 0;
result++;
que.push({nextx, nexty});
}
}
}
}
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>> matrix(n, vector<int>(m, 0));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>matrix[i][j];
}
}
/*
// dfs
for(int i=0; i<n; i++) {
if(matrix[i][0]){
pre_dfs(matrix, i, 0);
}
if(matrix[i][m-1]){
pre_dfs(matrix, i, m-1);
}
}
for(int j=0; j<m; j++){
if(matrix[0][j]){
pre_dfs(matrix, 0, j);
}
if(matrix[n-1][j]){
pre_dfs(matrix, n-1, j);
}
}
*/
// bfs
for(int i=0; i<n; i++) {
if(matrix[i][0]){
pre_bfs(matrix, i, 0);
}
if(matrix[i][m-1]){
pre_bfs(matrix, i, m-1);
}
}
for(int j=0; j<m; j++){
if(matrix[0][j]){
pre_bfs(matrix, 0, j);
}
if(matrix[n-1][j]){
pre_bfs(matrix, n-1, j);
}
}
result = 0;
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(matrix[i][j]){
// pre_dfs(matrix, i, j);
pre_bfs(matrix, i, j);
}
}
}
cout<<result;
return 0;
}
102. 沉没孤岛
本题是上一题的反向操作
先把非孤岛做访问标记,再对剩余陆地进行操作。
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
DFS
// c++
#include<bits/stdc++.h>
using namespace std;
int direction[][2] = {0, 1, 0, -1, -1, 0, 1, 0};
void pre_dfs(const vector<vector<int>>& matrix,
vector<vector<bool>>& visited,
int x, int y){
visited[x][y] = true;
for(int i=0; i<4; i++){
int nextx = x + direction[i][0];
int nexty = y + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty] && !visited[nextx][nexty]){
// visited[nextx][nexty] = true;
pre_dfs(matrix, visited, nextx, nexty);
}
}
}
void dfs(vector<vector<int>>& matrix,
vector<vector<bool>>& visited,
int x, int y){
matrix[x][y] = 0;
for(int i=0; i<4; i++){
int nextx = x + direction[i][0];
int nexty = y + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty] && !visited[nextx][nexty]){
visited[nextx][nexty] = true;
dfs(matrix, visited, nextx, nexty);
}
}
}
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>> matrix(n, vector<int>(m, 0));
vector<vector<bool>> visited(n, vector<bool>(m, false));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>matrix[i][j];
}
}
for(int i=0; i<n; i++){
if(matrix[i][0] && !visited[i][0]) pre_dfs(matrix, visited, i, 0);
if(matrix[i][m-1] && !visited[i][m-1]) pre_dfs(matrix, visited, i, m-1);
}
for(int j=0; j<m; j++){
if(matrix[0][j] && !visited[0][j]) pre_dfs(matrix, visited, 0, j);
if(matrix[n-1][j] && !visited[n-1][j]) pre_dfs(matrix, visited, n-1, j);
}
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(matrix[i][j] && !visited[i][j]){
visited[i][j] = true;
dfs(matrix,visited, i, j);
}
}
for(int j=0; j<m; j++) cout<<matrix[i][j]<<" ";
cout<<endl;
}
return 0;
}
BFS
//c++
#include<bits/stdc++.h>
using namespace std;
int direction[][2] = {0, 1, 0, -1, -1, 0, 1, 0};
void pre_dfs(const vector<vector<int>>& matrix,
vector<vector<bool>>& visited,
int x, int y){
visited[x][y] = true;
for(int i=0; i<4; i++){
int nextx = x + direction[i][0];
int nexty = y + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty] && !visited[nextx][nexty]){
// visited[nextx][nexty] = true;
pre_dfs(matrix, visited, nextx, nexty);
}
}
}
void dfs(vector<vector<int>>& matrix,
vector<vector<bool>>& visited,
int x, int y){
matrix[x][y] = 0;
for(int i=0; i<4; i++){
int nextx = x + direction[i][0];
int nexty = y + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty] && !visited[nextx][nexty]){
visited[nextx][nexty] = true;
dfs(matrix, visited, nextx, nexty);
}
}
}
void pre_bfs(const vector<vector<int>>& matrix,
vector<vector<bool>>& visited,
int x, int y){
visited[x][y] = true;
queue<pair<int, int>> que;
que.push({x,y});
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 + direction[i][0];
int nexty = cury + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty] && !visited[nextx][nexty]){
visited[nextx][nexty] = true;
que.push({nextx, nexty});
}
}
}
}
void bfs(vector<vector<int>>& matrix,
vector<vector<bool>>& visited,
int x, int y){
visited[x][y] = true;
matrix[x][y] = 0;
queue<pair<int, int>> que;
que.push({x,y});
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 + direction[i][0];
int nexty = cury + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty] && !visited[nextx][nexty]){
visited[nextx][nexty] = true;
matrix[nextx][nexty] = 0;
que.push({nextx, nexty});
}
}
}
}
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>> matrix(n, vector<int>(m, 0));
vector<vector<bool>> visited(n, vector<bool>(m, false));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>matrix[i][j];
}
}
/*
// dfs
for(int i=0; i<n; i++){
if(matrix[i][0] && !visited[i][0]) pre_dfs(matrix, visited, i, 0);
if(matrix[i][m-1] && !visited[i][m-1]) pre_dfs(matrix, visited, i, m-1);
}
for(int j=0; j<m; j++){
if(matrix[0][j] && !visited[0][j]) pre_dfs(matrix, visited, 0, j);
if(matrix[n-1][j] && !visited[n-1][j]) pre_dfs(matrix, visited, n-1, j);
}
*/
// bfs
for(int i=0; i<n; i++){
if(matrix[i][0] && !visited[i][0]) pre_bfs(matrix, visited, i, 0);
if(matrix[i][m-1] && !visited[i][m-1]) pre_bfs(matrix, visited, i, m-1);
}
for(int j=0; j<m; j++){
if(matrix[0][j] && !visited[0][j]) pre_bfs(matrix, visited, 0, j);
if(matrix[n-1][j] && !visited[n-1][j]) pre_bfs(matrix, visited, n-1, j);
}
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(matrix[i][j] && !visited[i][j]){
// visited[i][j] = true;
// dfs(matrix,visited, i, j);
bfs(matrix,visited, i, j);
}
}
for(int j=0; j<m; j++) cout<<matrix[i][j]<<" ";
cout<<endl;
}
return 0;
}
*103. 水流问题
使用两个标识访问的数组分别从两组边界出发进行dfs遍历,使用从低向高流(反向流)来分别记录两组边界的结点。最后两组边界的交集就是本题答案。
思路
时间复杂度:
O
(
m
∗
n
)
O(m*n)
O(m∗n)
空间复杂度:
O
(
m
∗
n
)
O(m*n)
O(m∗n)
// c++
#include<bits/stdc++.h>
using namespace std;
int direction[][2] = {0, 1, 0, -1, -1, 0, 1, 0};
void dfs(const vector<vector<int>> &matrix,
vector<vector<bool>> &visited,
int x, int y){
visited[x][y] = true;
for(int i=0; i<4; i++){
int nextx = x + direction[i][0];
int nexty = y + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
if(matrix[x][y]>matrix[nextx][nexty]) continue;
if(!visited[nextx][nexty]) dfs(matrix, visited, nextx, nexty);
}
}
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>> matrix(n, vector<int>(m, 0));
vector<vector<bool>> first(n, vector<bool>(m, false));
vector<vector<bool>> second(n, vector<bool>(m, false));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>matrix[i][j];
}
}
for(int i=0; i<n; i++){
dfs(matrix, first, i, 0);
dfs(matrix, second, i, m-1);
}
for(int j=0; j<m; j++){
dfs(matrix, first, 0, j);
dfs(matrix, second, n-1, j);
}
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(first[i][j] && second[i][j]) cout<<i<<" "<<j<<endl;
}
}
return 0;
}
*104. 建造最大岛屿
分两阶段。
- 先对地图中的陆地进行一次遍历,对每一个岛屿进行标记,同时计算每个岛屿的面积。
- 再对地图中的水域进行一次遍历,计算每一个水域变成陆地后的连续陆地面积,就是把水域四个方向的陆地面积求和,再加上1表示当前水域变为陆地。
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
// c++
#include<bits/stdc++.h>
using namespace std;
int direction[4][2] = {0, 1, 0, -1, -1, 0, 1, 0};
void dfs(vector<vector<int>> &matrix,
vector<vector<bool>> &visited,
int x, int y, int &count, int mark){
visited[x][y] = true;
matrix[x][y] = mark;
count++;
for(int i=0; i<4; i++){
int nextx = x + direction[i][0];
int nexty = y + direction[i][1];
if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
if(matrix[nextx][nexty] == 1 && !visited[nextx][nexty]){
dfs(matrix, visited, nextx, nexty, count, mark);
}
}
}
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>> matrix(n, vector<int>(m, 0));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
cin>>matrix[i][j];
}
}
vector<vector<bool>> visited(n, vector<bool>(m, false));
// 记录岛屿面积
unordered_map<int, int> markCount;
int mark = 2;
int count;
bool isAllGrid = true;
// 第一阶段:记录岛屿大小
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(matrix[i][j] == 0) isAllGrid = false;
if(matrix[i][j] == 1 && !visited[i][j]){
count = 0;
dfs(matrix, visited, i, j, count, mark);
markCount[mark] = count;
mark++;
}
}
}
if(isAllGrid) {
cout<<n*m<<endl;
return 0;
}
int result = 0;
// 第二阶段
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
// 非陆地 计算把当前水域变为陆地的最大面积
if(matrix[i][j] == 0){
unordered_set<int> lands;
// 把当前水域变为陆地
count = 1;
// 遍历当前水域的四个方向 把四个方向的陆地面积都加起来
for(int k=0; k<4; k++){
int nextx = i + direction[k][0];
int nexty = j + direction[k][1];
if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
// 当前陆地已加入
if(lands.count(matrix[nextx][nexty])>0) continue;
count += markCount[matrix[nextx][nexty]];
// 标记已加入的节点
lands.insert(matrix[nextx][nexty]);
}
}
result = max(result, count);
}
}
cout<<result;
return 0;
}