欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > 笔记:代码随想录算法训练营day58:101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿

笔记:代码随想录算法训练营day58:101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿

2025/6/17 0:37:41 来源:https://blog.csdn.net/jingjingjing1111/article/details/146403953  浏览:    关键词:笔记:代码随想录算法训练营day58:101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿

学习资料:代码随想录

文中含大模型生成内容

101. 孤岛的总面积

卡码网:101. 孤岛的总面积

所以找周边都是水的陆地的方法就是找边缘的陆地然后删除它连同它的连通的陆地

深搜
 

#include <iostream>
#include <vector>
using namespace std;int dir[4][2]={0,1,-1,0,0,-1,1,0};void dfs(vector<vector<int>>& fiji,int x,int y){fiji[x][y]=0;for(int i=0;i<4;i++){int xnext=x+dir[i][0];int ynext=y+dir[i][1];if(xnext<0||xnext>=fiji.size()||ynext<0||ynext>=fiji[0].size()) continue;if(fiji[xnext][ynext]==0)continue;else{dfs(fiji,xnext,ynext);}}
}
int main(){int n,m;cin>>n>>m;vector<vector<int>> fiji(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>fiji[i][j];}}for(int i=0;i<n;i++){if(fiji[i][0]==1){dfs(fiji,i,0);}if(fiji[i][m-1]==1){dfs(fiji,i,m-1);}}for(int j=0;j<m;j++){if(fiji[0][j]==1){dfs(fiji,0,j);}if(fiji[n-1][j]==1){dfs(fiji,n-1,j);}}int count =0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(fiji[i][j]==1) count++;}}cout<<count<<endl;
}

广搜
 

#include <iostream>
#include <vector>
#include <queue>
using namespace std;int dir[4][2]={0,1,-1,0,0,-1,1,0};void bfs(vector<vector<int>>& fiji,int x,int y){fiji[x][y]=0;queue<pair<int,int>> que;que.push({x,y});while(!que.empty()){pair<int,int> cur=que.front();que.pop();for(int i=0;i<4;i++){int xnext = cur.first+dir[i][0];int ynext = cur.second+dir[i][1];if(xnext<0||xnext>=fiji.size()||ynext<0||ynext>=fiji[0].size()) continue;if(fiji[xnext][ynext]==1){que.push({xnext,ynext});fiji[xnext][ynext]=0;}}}
}
int main(){int n,m;cin>>n>>m;vector<vector<int>> fiji(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>fiji[i][j];}}for(int i=0;i<n;i++){if(fiji[i][0]==1){bfs(fiji,i,0);}if(fiji[i][m-1]==1){bfs(fiji,i,m-1);}}for(int j=0;j<m;j++){if(fiji[0][j]==1){bfs(fiji,0,j);}if(fiji[n-1][j]==1){bfs(fiji,n-1,j);}}int count =0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(fiji[i][j]==1) count++;}}cout<<count<<endl;
}

深度优先搜索(DFS)或广度优先搜索(BFS) 中,我们通常用 visited 数组来标记已经访问过的点,以防止:

  • 重复访问,导致超时
  • 无限递归,导致栈溢出(Stack Overflow)

通常如果 不能修改原数组,我们就要 额外开一个 visited 数组 来记录访问情况。

这里的 grid 只有两种值:

  • 1(陆地)
  • 0(海洋)

我们遍历 grid 时:

  1. 遇到 1(陆地)

    • 说明它是未访问过的,然后我们调用 dfs(grid, x, y)
    • 在 DFS 里,我们把 grid[x][y] 直接改成 0,代表这个点已经被访问过了。
    • 这样,我们就不会 重复访问 这个点,也不会影响后续的 DFS 逻辑。
  2. 遇到 0(海洋)

    • 要么是原始的海洋
    • 要么是 DFS 过程中被修改成 0 的陆地
    • 不需要再访问,所以直接跳过
  3. 这样,我们实际上是用 grid 自己充当 visited 数组!

102. 沉没孤岛

卡码网题目链接(ACM模式)

先把边缘的陆地标记成2,然后把陆地1改成水0,最后把边缘的陆地改回1就可以了

深搜

#include <iostream>
#include <vector>
using namespace std;int dir[4][2]={0,1,-1,0,0,-1,1,0};
void dfs(vector<vector<int>>& fiji,int x,int y){fiji[x][y]=2;for(int i=0;i<4;i++){int xnext = x+dir[i][0];int ynext = y+dir[i][1];if(xnext<0||xnext>=fiji.size()||ynext<0||ynext>=fiji[0].size()) continue;if(fiji[xnext][ynext]==1){dfs(fiji,xnext,ynext);}}
}
int main(){int n,m;cin>>n>>m;vector<vector<int>> fiji(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>fiji[i][j];}}for(int i=0;i<n;i++){if(fiji[i][0]==1) dfs(fiji,i,0);if(fiji[i][m-1]==1) dfs(fiji,i,m-1);}for(int j=0;j<m;j++){if(fiji[0][j]==1) dfs(fiji,0,j);if(fiji[n-1][j]==1) dfs(fiji,n-1,j);}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(fiji[i][j]==2){fiji[i][j]=1;}else if(fiji[i][j]==1){fiji[i][j]=0;}cout<<fiji[i][j]<<' ';}cout<<endl;}}

 广搜

#include <iostream>
#include <vector>
#include <queue>
using namespace std;int dir[4][2]={0,1,-1,0,0,-1,1,0};
void dfs(vector<vector<int>>& fiji,int x,int y){queue<pair<int,int>> que;que.push({x,y});fiji[x][y]=2;while(!que.empty()){pair<int,int> cur=que.front();que.pop();for(int i=0;i<4;i++){int xnext = cur.first+dir[i][0];int ynext = cur.second+dir[i][1];if(xnext<0||xnext>=fiji.size()||ynext<0||ynext>=fiji[0].size()) continue;if(fiji[xnext][ynext]==1){que.push({xnext,ynext});fiji[xnext][ynext]=2;}}}
}
int main(){int n,m;cin>>n>>m;vector<vector<int>> fiji(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>fiji[i][j];}}for(int i=0;i<n;i++){if(fiji[i][0]==1) dfs(fiji,i,0);if(fiji[i][m-1]==1) dfs(fiji,i,m-1);}for(int j=0;j<m;j++){if(fiji[0][j]==1) dfs(fiji,0,j);if(fiji[n-1][j]==1) dfs(fiji,n-1,j);}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(fiji[i][j]==2){fiji[i][j]=1;}else if(fiji[i][j]==1){fiji[i][j]=0;}cout<<fiji[i][j]<<' ';}cout<<endl;}}

103. 水流问题

卡码网题目链接(ACM模式)

从边缘向中间搜索高点并记录

#include <iostream>
#include <vector>
using namespace std;
int dir[4][2]={0,1,-1,0,0,-1,1,0};void dfs(vector<vector<bool>>& visited,const vector<vector<int>>& fiji,int x,int y){if(visited[x][y]==true) return;visited[x][y] =true;for(int i=0;i<4;i++){int xnext = x+dir[i][0];int ynext = y+dir[i][1];if(xnext<0||xnext>=fiji.size()||ynext<0||ynext>=fiji[0].size()) continue;if(visited[xnext][ynext]==false&&fiji[x][y]<=fiji[xnext][ynext]){dfs(visited,fiji,xnext,ynext);}}}
int main(){int n,m;cin>>n>>m;vector<vector<int>> fiji(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>fiji[i][j];}}vector<vector<bool>> firstBorder(n,vector<bool>(m,0));vector<vector<bool>> secondBorder(n,vector<bool>(m,0)); for(int i=0;i<n;i++){dfs(firstBorder,fiji,i,0);dfs(secondBorder,fiji,i,m-1);}   for(int j=0;j<m;j++){dfs(firstBorder,fiji,0,j);dfs(secondBorder,fiji,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;}}}
}

一点小思考:第一种写法可否把visited改成全局变量然后时间复杂度也变成n*m?还是从两边往中间走合适,要不然使用全局visited并且还是用第一种方法遍历每一个点的话,遇到{{{2,2,2},{2,1,2}{2,2,2}},岂不是中间这个1也会被标记成true,这里是自己的思考,欢迎批评指正

104.建造最大岛屿

卡码网题目链接(ACM模式)

需要先遍历一遍给每块岛一个序号,记录数量,然后去搜索水域加上周围的岛,取最大值,

其中,岛的序号和面积用unordered_map记录

有一个有趣的一点是水周围的陆地可能是连在一起的,所以也要加上后就记录一下,用unordered_set记录

#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;int dir[4][2]={0,1,-1,0,0,-1,1,0};void dfs(vector<vector<int>>& fiji,vector<vector<bool>>& visited,int x,int y,int& mark,int& count){if(visited[x][y]==true) return;fiji[x][y]=mark;visited[x][y]=true;count++;for(int i=0;i<4;i++){int xnext = x+dir[i][0];int ynext = y+dir[i][1];if(xnext<0||xnext>=fiji.size()||ynext<0||ynext>=fiji[0].size()) continue;if(fiji[xnext][ynext]==0) continue;if(visited[xnext][ynext]==false&&fiji[xnext][ynext]==1){dfs(fiji,visited,xnext,ynext,mark,count);}}
}
int main(){int n,m;cin>>n>>m;vector<vector<int>> fiji(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>fiji[i][j];}}vector<vector<bool>> visited(n,vector<bool>(m,0));int mark=2;bool isLand = true;unordered_map<int,int> map;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(fiji[i][j]==0) isLand=false;if(fiji[i][j]==1&&visited[i][j]==false){int count=0;dfs(fiji,visited,i,j,mark,count);map[mark]=count;mark++;}}}if(isLand==true){cout<<n*m;return 0;}int result =0;int area=0;unordered_set<int> addedArea;for(int i=0;i<n;i++){for(int j=0;j<m;j++){addedArea.clear();if(fiji[i][j]==0){area = 0;for(int k=0;k<4;k++){int inext=dir[k][0]+i;int jnext=dir[k][1]+j;if(inext<0||inext>=fiji.size()||jnext<0||jnext>=fiji[0].size()) continue;if(addedArea.count(fiji[inext][jnext])!=0) continue;area+=map[fiji[inext][jnext]];addedArea.insert(fiji[inext][jnext]);}}result=max(area,result);}}cout<<result+1<<endl;
}

.

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词