【蓝桥杯】2023省赛F题--岛屿个数

题目 

知识点

BFS

思路

(海水染色)--> (造陆填海) --> (找到岛屿 --> 计数 --> 消灭岛屿)

        我们可以先在海边给海水染色(八个方向进行染色),将大海的颜色染为 ‘2’,染完颜色后颜色为‘0’的海水肯定是在环状岛屿的内部。

        其次由于环状岛屿内部的岛屿是不计数的,我们将环状岛屿填充为实心岛屿。

        最后,规定ans = 0,我们从(0,0)的位置开始搜索,如果遇到‘1’(岛屿)则ans ++,然后将与这个‘1’上下左右连接的‘1’全部变成‘2’(消灭岛屿),从(0,0)遍历到(x - 1, y - 1)。

        所有程序完成之后,输出ans的值。

        

代码

#include<bits/stdc++.h>
#define N 500010
#define int long long
using namespace std;
string s[60];
int x,y;
int idx = 0,idx1 = 0;
int ans = 0;
vector<pair<int,int>> q;
vector<pair<int,int>> sq;

void color()
{
    for(int i = 0; i < y; i ++)//第一行
    {
        if(s[0][i] == '0') {
            s[0][i] = '2';
            q.emplace_back(0,i);
        }
    }
    for(int i = 0; i < y; i ++)//最后一行
    {
        if(s[x - 1][i] == '0') {
            s[x - 1][i] = '2';
            q.emplace_back(x - 1,i);
        }
    }
    for(int i = 0; i < x; i ++)//第一列
    {
        if(s[i][0] == '0') {
            s[i][0] = '2';
            q.emplace_back(i,0);
        }
    }
    for(int i = 0; i < x; i ++)//最后一列
    {
        if(s[i][y - 1] == '0') {
            s[i][y - 1] = '2';
            q.emplace_back(i,y - 1);
        }
    }
}

void get_color()
{
    int dx[8] = {-1,-1,0,1,1,1,0,-1};
    int dy[8] = {0,-1,-1,-1,0,1,1,1};
    if(idx >= q.size()) return;
    else
    {
        int lx = q[idx].first;
        int ly = q[idx].second;
        for(int i = 0; i < 8; i ++)
        {
            if(lx + dx[i] >= 0 && lx + dx[i] < x && ly + dy[i] >= 0 && ly + dy[i] < y && s[lx + dx[i]][ly + dy[i]] == '0')
            {
                q.emplace_back(lx + dx[i],ly + dy[i]);
                s[lx + dx[i]][ly + dy[i]] = '2';
            }
        }
        idx ++;
        get_color();
    }
}

void get_land()
{
    for(int i =0; i < x; i ++)
    {
        for(int j = 0; j < y; j ++)
        {
            if(s[i][j] == '0')
                s[i][j] = '1';
        }
    }
}

void get_sum()
{
    int dx[4] = {-1,1,0,0};
    int dy[4] = {0,0,-1,1};
    if(idx1 >= sq.size()) return;
    else
    {
        int lx = sq[idx1].first;
        int ly = sq[idx1].second;
        for(int i = 0; i < 4; i ++)
        {
            if(lx + dx[i] >= 0 && lx + dx[i] < x && ly + dy[i] >= 0 && ly + dy[i] < y && s[lx + dx[i]][ly + dy[i]] == '1')
            {
                sq.emplace_back(lx + dx[i],ly + dy[i]);
                s[lx + dx[i]][ly + dy[i]] = '2';
            }
        }
        idx1 ++;
        get_sum();
    }
}

void solve()
{
    cin >> x >> y;

    for(int i = 0; i < x; i ++)
    {
        cin >> s[i];
    }
    //清洗容器
    ans = 0;
    idx = 0;
    q.clear();
    sq.clear();
    idx1 = 0;
    //染色
    color();
    get_color();
    //填海造陆
    get_land();
    //计算岛屿
    for(int i = 0; i < x; i ++)
    {
        for(int j = 0; j < y; j ++)
        {
            if(s[i][j] == '1')
            {
                sq.clear();
                idx1 = 0;
                s[i][j] = '2';
                ans ++;
                sq.emplace_back(i,j);
                get_sum();
            }
        }
    }
    cout << ans << endl;
}

int32_t main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int _;
//	_ = 1;
    cin >> _;
    while (_ --)
        solve();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只大黄猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值