自学内容网 自学内容网

代码随想录第五十一天

99.岛屿数量

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。

后续 N 行,每行包含 M 个数字,数字为 1 或者 0。

输出描述

输出一个整数,表示岛屿的数量。如果不存在岛屿,则输出 0。

输入示例

4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

输出示例

3

提示信息

数据范围:

1 <= N, M <= 50

第一种方法(深度优先搜索)

思路:

每个岛屿是由若干个相邻的 1(陆地)组成的连通区域,岛屿之间是通过上下左右相邻的陆地连接的。在实现过程中,首先会创建一个图(graph)来存储网格的值,并使用一个 path 数组来记录哪些位置已经被访问过。然后,通过逐个遍历网格中的每个位置,如果当前位置是 1 且未被访问过,就启动一次 DFS 遍历,从这个位置开始,将所有与其相连的 1 标记为已访问,这样就能找到并遍历整个岛屿。在 DFS 遍历过程中,会检查四个方向(上、下、左、右),确保每个位置都在网格的有效范围内。如果当前位置是 1 且未访问过,则继续向相邻的四个方向递归地进行 DFS 遍历,直到这个岛屿的所有陆地都被标记为已访问。每次找到一个未被访问的 1 时,就代表发现了一个新的岛屿,岛屿数量加 1。这样,最终可以统计出网格中岛屿的总数量。

解答:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> 
int** graph = NULL;
bool** path = NULL;
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
void DFS(int** graph,bool** path,int x,int y,int M,int N)
{
    for(int i = 0;i < 4;i++)
    {
        int nextx = x + dir[i][0];
        int nexty = y + dir[i][1];
        if(nextx < 0 || nextx >= M || nexty < 0 || nexty >= N)
        {
            continue;
        }
        if(!path[nextx][nexty] && graph[nextx][nexty] == 1)
        {
            path[nextx][nexty] = true;
            DFS(graph,path,nextx,nexty,M,N);
        }
    }
}
int main()
{
    int N,M;
    scanf("%d %d",&N,&M);
    graph = malloc(sizeof(int*)*N);
    for(int i = 0;i < N;i++)
    {
        graph[i] = malloc(sizeof(int)*M);
    }
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            scanf("%d",&graph[i][j]);   
        }    
    }
    path = malloc(sizeof(bool*)*N);
    for(int i = 0;i < N;i++)
    {
        path[i] = malloc(sizeof(bool)*M);
    }
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            path[i][j] = false;
        }
    }
    int count = 0;
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            if(graph[i][j] == 1 && !path[i][j])
            {
                path[i][j] = true;
                DFS(graph,path,i,j,N,M);
                count++;
            }
        }
    }
    printf("%d",count);
    return 0;
}

第二种方法(广度优先搜索)

思路:

首先,我们使用一个队列来存储待访问的节点,每次从队列中取出一个节点,并检查其四个方向(右、下、左、上)。对于每一个方向,若相邻的节点是陆地且未被访问过,就将该节点加入队列,并标记为已访问。这样,队列会不断扩展,直到岛屿中的所有陆地都被访问过。每当我们找到一个未被访问的陆地时,说明我们发现了一个新岛屿,因此开始新的 BFS 遍历,直到所有的岛屿都被标记完。在 main 函数中,我们读取输入网格,初始化 graphpath 数组,并在网格中每遇到一个未访问的陆地时调用 BFS,最终计算岛屿的总数。

解答:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> 
#define queue_node 1000
int queuex[queue_node];
int queuey[queue_node];
int front = 0;
int rear = 0;
int** graph = NULL;
bool** path = NULL;
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
int empty()
{
    return rear == front;    
}
void enqueue(int x,int y)
{
    queuex[rear] = x;
    queuey[rear] = y;
    rear++;
}
void popqueue(int* x,int* y)
{
    *x = queuex[front];
    *y = queuey[front];
    front++;
}
void BFS(int** graph,bool** path,int x,int y,int M,int N)
{
    enqueue(x,y);
    path[x][y] = true;
    while(!empty())
    {
        int X,Y;
        popqueue(&X,&Y);
        for(int i = 0;i < 4;i++)
        {
            int nextx = X + dir[i][0];
            int nexty = Y + dir[i][1];
            if(nextx < 0 || nextx >= N || nexty < 0 || nexty >= M)
            {
                continue;
            }
            if(!path[nextx][nexty] && graph[nextx][nexty] == 1)
            {
                enqueue(nextx,nexty);
                path[nextx][nexty] = true;
            }
        }
    }
}
int main()
{
    int N,M;
    scanf("%d %d",&N,&M);
    graph = malloc(sizeof(int*)*N);
    for(int i = 0;i < N;i++)
    {
        graph[i] = malloc(sizeof(int)*M);
    }
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            scanf("%d",&graph[i][j]);   
        }    
    }
    path = malloc(sizeof(bool*)*N);
    for(int i = 0;i < N;i++)
    {
        path[i] = malloc(sizeof(bool)*M);
    }
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            path[i][j] = false;
        }
    }
    int count = 0;
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            if(graph[i][j] == 1 && !path[i][j])
            {
                count++;
                BFS(graph,path,i,j,M,N);
            }
        }
    }
    printf("%d",count);
    return 0;
}

100.岛屿的最大面积

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,计算岛屿的最大面积。岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。后续 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。

输出描述

输出一个整数,表示岛屿的最大面积。如果不存在岛屿,则输出 0。

输入示例

4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

输出示例

4

提示信息

数据范围:

1 <= M, N <= 50。

思路:

首先,我们读取输入的二维地图,它由 10 组成,1 表示陆地,0 表示水域。然后,我们使用一个 path 数组来标记每个位置是否被访问过。程序从每个未访问的陆地(即 graph[i][j] == 1)开始执行 BFS,每当找到一个新的岛屿时,我们便计算该岛屿的面积。BFS 算法通过队列来逐层遍历岛屿,队列中的元素是一个个位置,每次我们从队列中弹出一个位置,并检查其四个方向的相邻位置(上下左右),若相邻位置是 1 且未被访问,则将其加入队列,继续扩展。对于每个岛屿,我们统计其面积,也就是计算 BFS 遍历到的 1 的个数。每次 BFS 结束后,更新最大岛屿面积,最终遍历完所有的点,程序将输出最大的岛屿面积。在实现时,队列用于存储待处理的陆地位置,队列的入队和出队操作确保了广度优先的顺序。每当处理完一个岛屿后,我们会清除已访问的标记,继续处理下一个未访问的陆地,直到所有的点都被遍历过为止。这样,最终我们能够找到并返回最大岛屿的面积。

解答:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#define queue_node 1000
int queuex[queue_node];
int queuey[queue_node];
int** graph = NULL;
bool** path = NULL;
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
int front = 0;
int rear = 0;
int count;
int empty()
{
    return rear == front;
}
void enqueue(int x,int y)
{
    queuex[rear] = x;
    queuey[rear] = y;
    rear++;
}
void popqueue(int* x,int* y)
{
    *x = queuex[front];
    *y = queuey[front];
    front++;
}
int BFS(int** graph,bool** path,int x,int y,int M,int N)
{
    enqueue(x,y);
    path[x][y] = true;
    while(!empty())
    {
        int curx,cury;
        popqueue(&curx,&cury);
        for(int i = 0;i < 4;i++)
        {
            int nextx = curx + dir[i][0];
            int nexty = cury + dir[i][1];
            if(nextx < 0 || nextx >= N || nexty < 0 || nexty >= M)
            {
                continue;
            }
            if(!path[nextx][nexty] && graph[nextx][nexty] == 1)
            {
                enqueue(nextx,nexty);
                count++;
                path[nextx][nexty] = true;
            }
        }
    }
    return count;
}
int main()
{
    int N,M;
    scanf("%d %d",&N,&M);
    graph = malloc(sizeof(int*)*N);
    for(int i = 0;i < N;i++)
    {
        graph[i] = malloc(sizeof(int)*M);
    }
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            scanf("%d",&graph[i][j]);   
        }    
    }
    path = malloc(sizeof(bool*)*N);
    for(int i = 0;i < N;i++)
    {
        path[i] = malloc(sizeof(bool)*M);
    }
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            path[i][j] = false;
        }
    }
    int max_result = 0;
    for(int i = 0;i < N;i++)
    {
        for(int j = 0;j < M;j++)
        {
            if(graph[i][j] == 1 && !path[i][j])
            {
                count = 1;
                int result = BFS(graph,path,i,j,M,N);
                if(max_result < result)
                {
                    max_result = result;
                }
            }
        }
    }
    printf("%d",max_result);
    return 0;
}

反思:

今天的题目都还好,都还是比较好懂的,对于深度优先搜索和广度优先搜索都有了一定的思考和认识。


原文地址:https://blog.csdn.net/2301_80630236/article/details/144276388

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!