今天一共两道题,第一道题的两种方法都是看题解之后才写出来的,主要是对图论中的DFS和BFS不太熟悉,有了第一题的基础,第二道题做起来很快。
岛屿数量 深搜(卡码网)
这道题需要定义一个递归函数,只要当前遍历的地点为陆地,就继续向其他方向探索,如果遇到水域则直接跳过本次循环,注意,该题定义的DFS函数在调用的时候只能将输入地点(x, y)所在的整个小岛探索出来,并不能将整个地图中的所有岛屿都探索出来,所以在主函数中需要多次调用DFS函数,这道题的DFS函数输入参数为:1.整个陆地与水域的0-1矩阵、探索过的陆地矩阵、当前位置的x,y坐标。
#include<iostream>
#include<vector>
using namespace std;
void dfs(const vector<vector<int>> &graph, vector<vector<bool>> &visited, int x, int y);
vector<vector<int>> dirs = { //定义4个搜索方向
{0, 1}, //向右
{0, -1}, //向左
{-1, 0}, //向上
{1, 0} //向下
};
int main(){
int M, N;
int result = 0;
cin >> N >> M; //N行M列
vector<vector<int>> graph(N, vector<int> (M, 0));
vector<vector<bool>> visited(N, vector<bool> (M, false));
for(int i = 0; i < N; i++){ //构造陆地和水构成的0-1矩阵
for(int j = 0; j < M; j++)
cin >> graph[i][j];
}
//遍历整个地图
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
if(graph[i][j] == 1 && !visited[i][j]){
//到达新的小岛
visited[i][j] = true; //标记为已到达
result++; //岛屿数量+1
dfs(graph, visited, i, j);
}
}
}
cout << result << endl;
return 0;
}
//深度优先搜索递归函数,调用该函数能够探索出(x, y)所在的整个小岛
//注意,调用该函数不能探索出整个地图的小岛
void dfs(const vector<vector<int>> &graph, vector<vector<bool>> &visited, int x, int y){
//输入参数分别为:陆地和水的矩阵、已经探索过的陆地,当前位置的x,y坐标
for(auto dir : dirs){
//下一步探索的坐标
int next_x = x + dir[0];
int next_y = y + dir[1];
if(next_x < 0 || next_x >= graph.size() || next_y < 0 || next_y >= graph[0].size())
continue; //访问越界,直接跳过
if(graph[next_x][next_y] == 1 && !visited[next_x][next_y]){
//探索到新的陆地
visited[next_x][next_y] = true; //标记为已探索
dfs(graph, visited, next_x, next_y);
}
}
}
岛屿数量 广搜(卡码网)
感觉广度优先搜索还是不够熟练,写的时候不知道该怎么实现,无语。看完题解以后写出来了,用广度优先搜索需要注意的一点是将遍历的地点加入队列中就要立马将visited数组中对应位置设置为true,要不然会超时,BFS函数也一样,调用一次只能将输入地点所在的岛屿探索出来,并不能将整个地图的岛屿探索出来,另外,BFS中不存在递归调用的情况,但是需要一个while循环来持续读取队列中的地点((x, y)上下左右的地点),这和BFS还是有很大区别的。
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
void bfs(const vector<vector<int>> &graph, vector<vector<bool>> &visited, int x, int y);
vector<vector<int>> dirs = { //定义4个搜索方向
{0, 1}, //向右
{0, -1}, //向左
{-1, 0}, //向上
{1, 0} //向下
};
int main(){
int M, N;
int result = 0;
cin >> N >> M; //N行M列
vector<vector<int>> graph(N, vector<int> (M, 0));
vector<vector<bool>> visited(N, vector<bool> (M, false));
for(int i = 0; i < N; i++){ //构造陆地和水构成的0-1矩阵
for(int j = 0; j < M; j++)
cin >> graph[i][j];
}
//遍历整个地图
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
if(graph[i][j] == 1 && !visited[i][j]){
//到达新的小岛
// visited[i][j] = true; //标记为已到达
result++; //岛屿数量+1
bfs(graph, visited, i, j);
}
}
}
cout << result << endl;
return 0;
}
//广度优先搜索函数,调用该函数能够探索出(x, y)所在的整个小岛
//注意,仅调用一次该函数不能探索出整个地图的小岛
void bfs(const vector<vector<int>> &graph, vector<vector<bool>> &visited, int x, int y){
//输入参数分别为:陆地和水的矩阵、已经探索过的陆地,当前位置的x,y坐标
queue<pair<int, int>> My_Queue; //用来存储到过的地方
My_Queue.push({x, y});
visited[x][y] = true; //只要入队,就立即标记为true
while(!My_Queue.empty()){
pair<int, int> current = My_Queue.front();
My_Queue.pop();
visited[current.first][current.second] = true; //将当前位置标记为来过
//开始从当前位置向四周探索
for(auto dir : dirs){
//下一步探索的坐标
int next_x = current.first + dir[0];
int next_y = current.second + dir[1];
if(next_x < 0 || next_x >= graph.size() || next_y < 0 || next_y >= graph[0].size())
continue; //访问越界,直接跳过
if(graph[next_x][next_y] == 1 && !visited[next_x][next_y]){
//探索到新的陆地
My_Queue.push({next_x, next_y});
visited[next_x][next_y] = true;
}
}
}
}
100.岛屿的最大面积
这道题BFS,DFS都可以,今天时间有限,我就直接用DFS写了,这道题的DFS函数需要额外定义一个输入参数S,通过引用的方式传入,在DFS函数中,每当到了一个新的地点,就将S加一。另外定义一个全局变量result,在主函数中每当到了一个全新的岛屿,调用DFS函数获取当前岛屿的面积,将result和S之间取较大值作为result的新值,其余地方和上一题差不多,这里不再赘述。
#include<iostream>
#include<vector>
using namespace std;
void dfs(const vector<vector<int>> &graph, vector<vector<bool>> &visited, int x, int y, int &S);
vector<vector<int>> dirs = {
{0, 1}, //向右
{0, -1}, //向左
{-1, 0}, //向上
{1, 0} //向下
};
int main(){
int M, N;
int result = 0;
cin >> N >> M; //N行M列
vector<vector<int>> graph(N, vector<int> (M, 0));
vector<vector<bool>> visited(N, vector<bool> (M, false));
for(int i = 0; i < N; i++){ //构造陆地和水构成的0-1矩阵
for(int j = 0; j < M; j++)
cin >> graph[i][j];
}
//开始遍历整个地图
for(int i = 0; i < N; i++){
for(int j = 0; j < M; j++){
if(graph[i][j] == 1 && !visited[i][j]){
//到达全新的小岛
visited[i][j] = true;
int S = 1; //用来记录当前小岛的面积
dfs(graph, visited, i, j, S);
result = max(result, S);
}
}
}
cout << result << endl;
return 0;
}
//深度优先搜索递归函数,调用该函数能够探索出(x, y)所在的整个小岛
//注意,调用该函数不能探索出整个地图的小岛
void dfs(const vector<vector<int>> &graph, vector<vector<bool>> &visited, int x, int y, int &S){
//输入参数为:小岛矩阵、已经探索过的地方矩阵、当前地点的x、y坐标
for(auto dir : dirs){
int next_x = x + dir[0];
int next_y = y + dir[1];
if(next_x < 0 || next_x >= graph.size() || next_y < 0 || next_y >= graph[0].size())
continue; //访问越界,直接跳过
if(graph[next_x][next_y] == 1 && !visited[next_x][next_y]){
//来到从没来过的陆地
S++; //面积加一
visited[next_x][next_y] = true;
dfs(graph, visited, next_x, next_y, S);
}
}
}
最近当助教挺累的,下班。