传送门:题目
题意:
一个人在迷宫里,点为可走,星为不可走,要求这个人走k步,恰好回到初始位置,并且保证路径的字典序最小。
题解:
如果没有字典序最小这个限制条件,我们大可以不必BFS,直接找到一个可行方块,来回来回走即可,但是题目要求字典序最小,所以我们只能先尝试字典序最小的D,也就是往下走,如果不行,在往L走,然后是RU。这里BFS一遍就好。但是怎么保证它能恰好回到起始点呢?我们可以先做个BFS预处理,把每一点距离初始点的距离记录下来,然后第二次BFS的时候,卡距离,这样就能保证回到初始点了。
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;
const int nx[] = {1, 0, 0, -1}, ny[] = {0, -1, 1, 0};//这里是按照DLRU顺序初始化的
const int maxn = 1010;
int n, m, k, start_x, start_y, dis[maxn][maxn];
string s[maxn], greed = "DLRU", ans;
queue<pair<int, int> > que;//BFS队列
bool Valid(int x, int y) {//判断越界
if (x >= 0 and x<n and y >= 0 and y < m and s[x][y] != '*')
return true;
return false;
}
int main(void) {
cin >> n >> m >> k;
if (k & 1)
return 0 * puts("IMPOSSIBLE");
for (int i = 0; i < n; i++) {//初始化地图
cin >> s[i];
for (int j = 0; j < m; j++) {
if (s[i][j] == 'X')
start_x = i, start_y = j;
dis[i][j] = INF;
}
}
que.emplace(start_x, start_y);
dis[start_x][start_y] = 0;
while (!que.empty()) {//第一遍BFS
int x = que.front().first, y = que.front().second;
que.pop();
for (int i = 0; i < 4; i++) {
int next_x = x + nx[i], next_y = y + ny[i];
if (Valid(next_x, next_y) and dis[next_x][next_y] > dis[x][y] + 1)
que.emplace(next_x, next_y), dis[next_x][next_y] = dis[x][y] + 1;
}
}
int x = start_x, y = start_y, dir;
for (int i = 0; i < k; i++) {//第二遍BFS
for (dir = 0; dir < 4; dir++) {
int next_x = x + nx[dir], next_y = y + ny[dir];
if (Valid(next_x, next_y) and dis[next_x][next_y] <= k - i - 1)//通过限制距离保证路线是一个圈
break;
}
if (dir == 4)
return 0 * puts("IMPOSSIBLE");
x += nx[dir];
y += ny[dir];
ans += greed[dir];
}
cout << ans << endl;
return 0;
}