最终状态是除了障碍物所有的点都要经过,要求最少步数,可以考虑bfs,dist[x1][y1][x2][y2]无法表示全部状态,所以还需要加上一维表示现在的状态,数据范围小,可以使用状态压缩。
#include <bits/stdc++.h>
using namespace std;
int n, m;
const int N = 5;
char g[N][N];
int sx, sy;
int dis[1 << 16][N][N][N][N];
struct T {
int st;
int x1, y1, x2, y2;
};
int s;
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
int cal(int x, int y) {
return 1 << (x * m + y);//下标从0开始可以使用这个小技巧把二维压缩成一维,然后看哪个点被遍历这个点的状态就是1;
}
int bfs(int state) {
queue<T> q;
memset(dis, -1, sizeof dis);
T start = {s, sx, sy, sx, sy};
dis[s][sx][sy][sx][sy] = 0;
q.push(start);
while (q.size()) {
auto t = q.front();
if (t.st == state) return dis[t.st][t.x1][t.y1][t.x2][t.y2];
q.pop();
for (int i = 0; i < 4; i++) {
int atx = t.x1 + dx[i], aty = t.y1 + dy[i];
if (atx<0 or atx>=n or aty<0 or aty>=m or g[atx][aty] == 'X') continue;
for (int j = 0; j < 4; j++) {
int btx = t.x2 + dx[j], bty = t.y2 + dy[j];
if (btx<0 or btx>=n or bty>=m or bty<0 or g[btx][bty] == 'X') continue;
int nst = t.st | cal(atx, aty) | cal(btx, bty);
if (dis[nst][atx][aty][btx][bty] ==-1) {
dis[nst][atx][aty][btx][bty] = dis[t.st][t.x1][t.y1][t.x2][t.y2] + 1;
q.push({nst, atx, aty, btx, bty});
}
}
}
}
return -1;
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) cin >> (g[i]);
int state = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (g[i][j] == 'S') sx = i, sy = j, s |= cal(i, j);
if (g[i][j] == 'S' or g[i][j] == 'O') state |= cal(i, j);
}
}
printf("%d\n", bfs(state));
return 0;
}