【ACWing】1098. 城堡问题

题目地址:

https://www.acwing.com/problem/content/1100/

     1   2   3   4   5   6   7  
   #############################
 1 #   |   #   |   #   |   |   #
   #####---#####---#---#####---#
 2 #   #   |   #   #   #   #   #
   #---#####---#####---#####---#
 3 #   |   |   #   #   #   #   #
   #---#########---#####---#---#
 4 #   #   |   |   |   |   #   #
   #############################

   #  = Wall   
   |  = No wall
   -  = No wall

   方向:上北下南左西右东。

上图是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成 m ∗ n m∗n mn个方格区域,每个方格区域可以有 0 ∼ 4 0\sim 4 04面墙。注意:墙体厚度忽略不计。

输入格式:
第一行包含两个整数 m m m n n n,分别表示城堡南北方向的长度和东西方向的长度。接下来 m m m行,每行包含 n n n个整数,每个整数都表示平面图对应位置的方块的墙的特征。每个方块中墙的特征由数字 P P P来描述,我们用 1 1 1表示西墙, 2 2 2表示北墙, 4 4 4表示东墙, 8 8 8表示南墙, P P P为该方块包含墙的数字之和。例如,如果一个方块的 P P P 3 3 3,则 3 = 1 + 2 3 = 1 + 2 3=1+2,该方块包含西墙和北墙。城堡的内墙被计算两次,方块 ( 1 , 1 ) (1,1) (1,1)的南墙同时也是方块 ( 2 , 1 ) (2,1) (2,1)的北墙。输入的数据保证城堡至少有两个房间。

输出格式:
共两行,第一行输出房间总数,第二行输出最大房间的面积(方块数)。

数据范围:
1 ≤ m , n ≤ 50 1≤m,n≤50 1m,n50
0 ≤ P ≤ 15 0≤P≤15 0P15

可以用BFS。这里需要将每个数的二进制位与四个方向做个对应, 1 = 2 0 1=2^0 1=20西墙,是第 0 0 0个方向; 2 = 2 1 2=2^1 2=21北墙,是第 1 1 1个方向; 4 = 2 2 4=2^2 4=22东墙,是第 2 2 2个方向; 8 = 2 3 8=2^3 8=23南墙,是第 3 3 3个方向。可以采用一个技巧,令数组 d = [ 0 , − 1 , 0 , 1 , 0 ] d=[0,-1,0,1,0] d=[0,1,0,1,0],这样 d [ 0 , 1 , 2 , 3 ] d[0,1,2,3] d[0,1,2,3]分别代表的就是西北东南四个墙的方向。代码如下:

#include <iostream>
#include <queue>
using namespace std;

const int N = 55, d[] = {0, -1, 0, 1, 0};
int m, n;
int a[N][N];
bool st[N][N];
queue<pair<int, int> > q;

int bfs(int x, int y) {
    int area = 1;
    q.push({x, y});
    st[x][y] = true;

    while (!q.empty()) {
        auto t = q.front();
        q.pop();
        for (int i = 0; i < 4; i++) {
            int nx = t.first + d[i], ny = t.second + d[i + 1];
            // 不能出界
            if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
            // 不能之前已经访问过
            if (st[nx][ny]) continue;
            // 不能撞墙
            if (a[t.first][t.second] >> i & 1) continue;

            q.push({nx, ny});
            st[nx][ny] = true;
            area++;
        }
    }

    return area;
}

int main() {
    cin >> m >> n;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            cin >> a[i][j];

    int cnt = 0, area = 0;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            if (!st[i][j]) {
                area = max(area, bfs(i, j));
                cnt++;
            }

    cout << cnt << endl;
    cout << area << endl;

    return 0;
}

时空复杂度 O ( m n ) O(mn) O(mn)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值