宣传一下算法提高课整理 <—
CSDN个人主页:更好的阅读体验 <—
题目传送门点这里
题目描述
1 2 3 4 5 6 7
#############################
1 # | # | # | | #
#####---#####---#---#####---#
2 # # | # # # # #
#---#####---#####---#####---#
3 # | | # # # # #
#---#########---#####---#---#
4 # # | | | | # #
#############################
(图 1)
# = Wall
| = No wall
- = No wall
方向:上北下南左西右东
输入格式
图1是一个城堡的地形图。
请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。
城堡被分割成 $m∗n$
个方格区域,每个方格区域可以有0~4面墙。
注意:墙体厚度忽略不计。
输出格式
第一行包含两个整数 $m$ 和 $n$ ,分别表示城堡南北方向的长度和东西方向的长度。
接下来 $m$ 行,每行包含 $n$ 个整数,每个整数都表示平面图对应位置的方块的墙的特征。
每个方块中墙的特征由数字 $P$ 来描述,我们用1表示西墙,2表示北墙,4表示东墙,8表示南墙, $P$ 为该方块包含墙的数字之和。
例如,如果一个方块的 $P$ 为3,则 3 = 1 + 2,该方块包含西墙和北墙。
城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。
输入的数据保证城堡至少有两个房间。
数据范围
$1≤m,n≤50,$
$0≤P≤15$
样例输入
4 7
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13
样例输出
5
9
思路
这道题除了是用数字表示每个房间的墙的方向,其它的与上一题 池塘计数 类似。
处理墙的方向,我们想到把 $P$ 用 二进制 表示,分成 $1,2,4,8$ 四面墙。
回忆一下怎么知道一个数 $x$ 二进制表示的第 $k$ 位:
x >> k & 1
熟悉了这部,就可以开始做题了。细节部分看代码。
AC Code
$C++$
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 55;
int dx[] = {0, -1, 0, 1};
int dy[] = {-1, 0, 1, 0}; // 四方向偏移量
int n, m;
int a[N][N]; // 每个房间p值
bool st[N][N]; // 每个房间有没有被遍历过
int res, Smax; // res表示答案,Smax表示最大面积
queue<PII> q; // BFS的队列,也可以手写
void bfs(int x, int y)
{
q.push({x, y}); // 起点入队
st[x][y] = true;
int sum = 1;
while (q.size())
{
auto t = q.front(); // 弹出队头
q.pop();
int X = t.first, Y = t.second;
for (int i = 0; i < 4; i ++ )
{
int xx = X + dx[i], yy = Y + dy[i]; // 向4个方向扩展
if (xx < 0 || yy < 0 || xx >= n || yy >= m) continue; // 出界
if (st[xx][yy] || a[X][Y] >> i & 1) continue; // 有墙
q.push({xx, yy}); // 否则加入队列
st[xx][yy] = 1;
sum ++ ;
}
}
Smax = max(Smax, sum);
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
scanf("%d", &a[i][j]);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (!st[i][j])
bfs(i, j), res ++ ;
printf("%d\n%d\n", res, Smax);
return 0;
}
最后,如果觉得对您有帮助的话,点个赞再走吧!