给定一个由 1(陆地)和 0(水)组成的矩阵,你最多可以将矩阵中的一格水变为一块陆地,在执行了此操作之后,矩阵中最大的岛屿面积是多少。
岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设矩阵外均被水包围。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
输出描述
输出一个整数,表示最大的岛屿面积。
#include<algorithm>
#include<iostream>
const int N =60;
/// @brief
int n,m;
using namespace std;
#include<vector>
#include <unordered_map>
#include <unordered_set>
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};//定义方向向量
int ans;
void dfs(int x,int y,int mark,vector<vector<int>>&g,vector<vector<bool>>&vis){
if(vis[x][y]||g[x][y]==0){
return;
}
vis[x][y]=true;//标记访问了,然后从这个点开始往四周搜索
g[x][y]=mark;//打上标签,代表是编号为mark的土地
ans++;//面积+1,编号为mark的面积+1
for(int i=0;i<4;i++){
int nx=x+dir[i][0];
int ny=y+dir[i][1];
if(nx<0||ny<0||nx>n-1||ny>m-1) continue;//越界了,就跳过这个点
dfs(nx,ny,mark,g,vis);
}
}
int main(){
cin>>n>>m;
vector<vector<int>>g(n,vector<int>(m,0));//创建一个图,把数据存进去
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>g[i][j];
bool isall=true;//是否全是陆地,如果是,那么直接输出n*m就好了
int mark=2;//编号从2开始,因为1代表了陆地
vector<vector<bool>>vis(n,vector<bool>(m,false));//用来标记是否访问过
unordered_map<int ,int> gridNum;//表示编号为i的土地面积是2;
unordered_set<int> gv;//是否已经用过这片土地了
//第一步,先把各个分割的陆地面积求出来;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(g[i][j]==0) //只要出现了一个海就说明不是全大陆
isall=false;//不是全大陆
if(!vis[i][j]&&g[i][j]==1){
//1
ans=0;
dfs(i,j,mark,g,vis);
//扫完之后,ans就可以存储了
gridNum[mark]=ans;//编号为mark的面积是ans;
mark++;//每次遍历完都意味着一块区域的搜索完成,因此需要加加编号
}
}
}
if(isall){
printf("%d",n*m);
return 0;
}
int result=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int count=1;//将一块海洋变为陆地,所以最少都有1
gv.clear();//每次要重置,因为对于任何一个海洋来说,他对于各个编号的陆地影响是不同的
if(g[i][j]==0){//找到一个海洋,试图把它变为陆地看看,对于其他土地的影响
for(int k=0;k<4;k++){
int nx=i+dir[k][0];
int ny=j+dir[k][1];
if(nx<0||ny<0||nx>n-1||ny>m-1){
continue;//越界跳过
}
if(gv.count(g[nx][ny])){
continue;
}
gv.insert(g[nx][ny]);//这个编号岛屿已经影响过了
count+=gridNum[g[nx][ny]];
}
}
result=max(result,count);
}
}
cout<<result<<endl;
return 0;
}
思路写的很详细了,大概就是,先把每个独立区域的陆地面积算出来
之后枚举每一个海洋,看看他会对每个板块造成怎样的影响,把面积都存起来,取最大值