AcWing 4959. 岛屿个数 以及其模板题 luoguP1162填涂颜色

#include <bits/stdc++.h> //实测用万能头与直接写头文件时间没什么区别

using namespace std;

const int N = 60;

typedef pair<int, int> PII;

char ma[N][N]; //注意题目中0 1 是以字符的形式输入的 要定义成char 注意审题 不能取名map会冲突
int n, m; 
int T;
int res; //定义答案 岛屿个数
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};  //岛屿坐标偏移量 四个方向
int dxx[8] = {1, -1, 0, 0, 1, 1, -1, -1}, dyy[8] = {0, 0, 1, -1, 1, -1, -1, 1}; //海水坐标偏移量 八个方向
bool st[N][N]; //判断当前点有没有被搜索过

//搜索岛屿 利用bfs板子
void bbfs(int x, int y)
{
    res ++ ; //利用函数一次证明就搜到了一个全新的岛屿 计入答案
    queue<PII> q;
    q.push({x, y});
    st[x][y] = true;
    while (q.size())
    {
        auto t = q.front(); //取出队头
        q.pop();
        for (int i = 0; i < 4; i ++ )
        {
            int a = t.first + dx[i], b = t.second + dy[i];
            if (a >= 0 && a <= n + 1 && b >= 0 && b <= m + 1 && !st[a][b] && ma[a][b] == '1') //搜下一个是陆地的点 找到这个岛屿的全部点
            {
                st[a][b] = true;
                q.push({a, b});
            }
        }
    }
}

//搜索海水 也利用bfs板子
void bfs(int x, int y)
{
    queue<PII> q;
    q.push({x, y});
    st[x][y] = true; //将该点标记为搜过了
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        for (int i = 0; i < 8; i ++ )
        {
            int a = t.first + dxx[i], b = t.second + dyy[i];
            if (a >= 0 && a <= n + 1 && b >= 0 && b <= m + 1 && !st[a][b]) //当前点没搜过
            {
                if (ma[a][b] == '1') bbfs(a, b); //去搜岛屿函数里把这个点所在的岛屿上的点全搜了 并全部标记为搜过 进入该函数一次 答案res岛屿个数就加1
                else 
                {
                    st[a][b] = true; //如果该点不是岛屿 也标记为搜过
                    q.push({a, b}); //入队 继续搜下一个也是海水的点
                }
            }
        }
    }
}

int main()
{
    scanf("%d", &T);
    while ( T -- )
    {
        //由于有多组测试数据 每次循环开始时 把所有要用到的数组和答案岛屿个数全部清空
        memset(st, 0, sizeof st);
        res = 0;
        memset(ma, '0' , sizeof ma);
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= m; j ++ )
                cin >> ma[i][j];                 //矩阵不能用scanf("%d", &ma[i][j])来读 我目前也不知道为什么!!! (可能是输入的数据之间没有空格?3.31
                //注意这里有一个很巧妙的点 
                //我们之所以将地图从(1,1)开始存 是因为我们要在外圈扩展一圈海水
                //保证我们下面从bfs(0,0)开始搜索时,不会产生(0,0)这个点就是陆地的情况导致我们无法进入bfs(),
                //(bfs()搜索海水点的函数 得保证输入的这个点(x,y)本身是海水
                //也不会产生点(0, 0) 被陆地包围的情况 海水无法向外扩展点读入 (如图1)

        bfs(0, 0); //从海水点(0, 0)开始向外扩展搜索

        printf("%d\n", res);
    }
    return 0;
}

screenshot-1711553509830.png
我们可以发现这组数据如果不把海水向外扩展一圈 (0, 0)一开始搜索就会直接碰到全部陆地 bfs函数内队列直接清空 无法继续执行函数


模板题 填涂颜色

填涂颜色

题目描述

由数字 \(0\) 组成的方阵中,有一任意形状的由数字 \(1\) 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 \(2\)。例如:\(6\times 6\) 的方阵(\(n=6\)),涂色前和涂色后的方阵如下:

如果从某个 \(0\) 出发,只向上下左右 \(4\) 个方向移动且仅经过其他 \(0\) 的情况下,无法到达方阵的边界,就认为这个 \(0\) 在闭合圈内。闭合圈不一定是环形的,可以是任意形状,但保证闭合圈内\(0\) 是连通的(两两之间可以相互到达)。

0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 1 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 1 2 1
1 1 1 1 1 1

输入格式

每组测试数据第一行一个整数 \(n(1 \le n \le 30)\)

接下来 \(n\) 行,由 \(0\)\(1\) 组成的 \(n \times n\) 的方阵。

方阵内只有一个闭合圈,圈内至少有一个 \(0\)

输出格式

已经填好数字 \(2\) 的完整方阵。

样例 #1

样例输入 #1

6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1

样例输出 #1

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1

提示

对于 \(100\%\) 的数据,\(1 \le n \le 30\)

#include <bits/stdc++.h>

using namespace std;

const int N = 40;

typedef pair<int, int> PII;

int ma[N][N];
int n;
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
int dxx[8] = {1, -1, 0, 0, 1, -1, 1, -1}, dyy[8] = {0, 0, 1, -1, 1, 1, -1, -1};
bool st[N][N];

void bbfs(int x, int y)
{
    queue<PII> q;
    q.push({x, y});
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        for (int i = 0; i < 8; i ++ )
        {
            int a = t.first + dxx[i], b = t.second + dyy[i];
            if (a >= 0 && a <= n + 1 && b >= 0; b <= n + 1 && !st[a][b] && ma[a][b] == 1)
            {   //这里if底下必须要加括号把下面代码扩起来 不是说向后空四格下面两行代码就都归if管,要不然答案错误 
                q.push({a, b});  //一定要注意细节 不要为了代码美观丧失准确性
                st[a][b] = true;
            }
        }
    }
}

void bfs(int x, int y)
{
    queue<PII> q;
    q.push({x, y});
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        for (int i = 0; i < 4; i ++ )
        {
            int a = t.first + dx[i], b = t.second + dy[i];
            if (a >= 0 && a <= n + 1 && b >= 0 && b <= n + 1 && !st[a][b])
            {
                if (ma[a][b] == 1) bbfs(a, b);
                else
                {
                    q.push({a, b});
                    st[a][b] = true;
                }
            }
        }
    }
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= n; j ++ )
            scanf("%d", &ma[i][j]);
    bfs(0, 0);        
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= n; j ++ )
        {
            if (!st[i][j]) ma[i][j] = 2;
        }

    for (int i = 1; i <= n; i ++ )
    {
        for (int j = 1; j <= n; j ++ )
            printf("%d ", ma[i][j]);
        cout << endl;
    }
    return 0;
}
posted @ 2024-04-16 17:32  MsEEi  阅读(11)  评论(0)    收藏  举报