分析
感觉没有蓝题难度
一道 bfs 题目,相较于大部分 bfs 题,它较为复杂,但分析一下还是很好水过的。
建立墙时,可以用三维数组,\(wall_{~i, ~j, ~pos}\) 表示 第 \(i\) 行第 \(j\) 列 \(pos\) 方向有墙。
观察发现,\(8 = 2^3,4 = 2^2,2 = 2^1,1 = 2^1\),于是可以用位运算快速储存。这里给出代码方便理解。
void build(int x, int y, int w)
{
if (w & 8)wall[x][y][0] = 1;
if (w & 4)wall[x][y][1] = 1;
if (w & 2)wall[x][y][2] = 1;
if (w & 1)wall[x][y][3] = 1;
}
接下来就是 bfs 的过程,在 bfs 时,保存下答案,以及这个房间的编号和这个房间的大小,对于接下来的拆墙有用。
对于拆墙,前面保存的编号和房间大小有了作用,遍历行和列,并只看东墙和北墙,如果墙后与当前格子的编号相同,直接跳过,否则更新答案。
注意:遍历时先遍历列,再遍历行,然后选择北墙,最后是东墙,因为题目说明西边的更优,然后是更南的,最后同一格子下,北边的更优,详细的可以看代码说明。
Accepted Code
/*Code By Manipula*/
#include <bits/stdc++.h>
using namespace std;
const int N = 55;
int mp[N][N], wall[N][N][4], space[N], num, ans1, ans2, ax, ay, n, m;
int fx[4] = {1, 0, -1, 0}, fy[4] = {0, 1, 0, -1};
char dir;
void build(int x, int y, int w)
{
if (w & 8)wall[x][y][0] = 1;
if (w & 4)wall[x][y][1] = 1;
if (w & 2)wall[x][y][2] = 1;
if (w & 1)wall[x][y][3] = 1;
}
struct Node{
int x, y;
};
queue<Node> q;
void bfs(int sx, int sy)
{
q.push((Node){sx, sy});
mp[sx][sy] = ++num;//记编号
int ret = 1;
while (!q.empty())
{
int x = q.front().x, y = q.front().y; q.pop();
for (int i = 0; i < 4; i++)
{
int xx = x + fx[i], yy = y + fy[i];
if (xx < 1 || xx > n || yy < 1 || yy > m)continue;
if (mp[xx][yy] || wall[x][y][i])continue;
mp[xx][yy] = num;
q.push((Node){xx, yy});
ret++;
}
}
ans1 = max(ans1, ret);
space[num] = ret;
}
int main()
{
cin >> n >> m; n ^= m ^= n ^= m;//交换一下,个人喜欢 n 为行数, m 为列数
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
int w; cin >> w;
build(i, j, w);
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (!mp[i][j])bfs(i, j);
for (int j = 1; j <= m; j++)//选择最西的
for (int i = n; i >= 1; i--)//选择最南的
for (int pos = 2; pos >= 1; pos--)//优先选择北边的墙
if (wall[i][j][pos])
{
int xx = i + fx[pos], yy = j + fy[pos];
if (mp[i][j] == mp[xx][yy])continue;//特判,如果他们的编号相同就不计算
if (space[mp[i][j]] + space[mp[xx][yy]] > ans2)
{
ans2 = space[mp[i][j]] + space[mp[xx][yy]];
ax = i; ay = j; dir = (pos == 1 ? 'E' : 'N');
}
}
cout << num << endl << ans1 << endl;
cout << ans2 << endl << ax << " " << ay << " " << dir;
return 0;
}
标签:P1457,int,题解,pos,yy,wall,xx,mp,USACO2.1
From: https://www.cnblogs.com/Manipula/p/17758258.html