1020 CSL的校园卡 bfs + 状态压缩DP
链接:https://ac.nowcoder.com/acm/problem/17872
来源:牛客网
题目描述
但是,等到他回来的时候,发现他的校园卡不见了,于是他需要走遍校园寻找它的校园卡。CSL想要尽快地找回他掉的校园卡,于是便求助于OneDay帮他一起找。
OneDay和CSL在同一已知的地点出发,并以相同的速度(1格/秒)搜索校园,试求两人走遍校园的最短时间。
输入描述:
第一行为两个整数n,m(1 ≤ n, m ≤ 4),表示地图的大小。接下来是n行m列的地图:X表示障碍物,S表示起点,O表示空地。障碍物不能直接经过,数据保证所有空地是可达的,起点有且只有一个。
输出描述:
输出一个整数表示两人共同走遍校园所需的最少时间。
分析
1.一开始实在想不通他是怎么写的,哪有bfs同时往两边走,而且怎么表示哪些点走过哪些点没走过??
2.后来发现这个bfs还真是往两边走的,记录的vis都是五维的其中四个表示位置,至于怎么表示哪些点走过,用的是状态压缩DP
3.然后开始写,但是没过多久就wa。确实有很多小错误,但是到了最后都改不出来,甚至和代码对过了。。
4.然后就放弃了
#include <bits/stdc++.h>
using namespace std;
char s[5][10];
bool vis[int(1 << 16) + 1][5][5][5][5];
struct node
{
int all, s, t, x, y, step;
};
int sum = 0, n, m, d[4][2] = {0, 1, 0, -1, -1, 0, 1, 0};
int bfs(int sx, int sy)
{
vis[1 << (sx * 4 + sy)][sx][sy][sx][sy] = 1;
queue<node>q;
q.push({1 << (sx * 4 + sy), sx, sy, sx, sy, 0});
while (q.size()) {
auto p = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
int nx = p.s + d[i][0], ny = p.t + d[i][1];
if (nx < 0 || nx >= n || ny < 0 || ny >= m || s[nx][ny] == 'X') continue;
for (int j = 0; j < 4; j++)
{
int nnx = p.x + d[j][0], nny = p.y + d[j][1];
int st = p.all | (1 << (nx * 4 + ny)) | (1 << (nnx * 4 + nny));
if (nnx < 0 || nnx >= n || nny < 0 || nny >= m || s[nnx][nny] == 'X' || vis[st][nx][ny][nnx][nny]) continue;
if (st == sum) return p.step + 1;
vis[st][nx][ny][nnx][nny] = 1;
q.push({st, nx, ny, nnx, nny, p.step + 1});
}
}
}
return 0;
}
int main()
{
cin >> n >> m;
int sx, sy;
for (int i = 0; i < n; i++)
{
cin >> s[i];
for (int j = 0; j < m; j++)
if (s[i][j] == 'S') sx = i, sy = j,sum += (1 << (4 * i + j));
else if(s[i][j] == 'O') sum += (1 << (4 * i + j));
}
cout << bfs(sx, sy) << endl;
return 0;
}