☀️☃️☃️☃️☀️ • 8个月前
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int d[31][31][4]; //d[i][j][k] 表示箱子在(i,j)人箱子的在 k=上/左/下/右 的情况下 箱子的最少移动步数
char map[31][31];
bool vis[31][31];
struct point {
int i, j , p;
};
queue<point>Q;
void toNearBox(int pi, int pj, int bi, int bj ,int step) { //检查人从(pi,pj)出发,能够到达的所有和箱子(bi,bj)的相邻位置,并把状态加入箱子移动的BFS队列
memset(vis, 0, sizeof vis); //因为人移动的步数不算,所以只要记录人是否到过这个位置就够了
queue<point>Q2; //人的移动也得是bfs
Q2.push({ pi, pj });
vis[pi][pj] = true;
while (!Q2.empty() && (d[bi][bj][0] == 0 || d[bi][bj][1] == 0 || d[bi][bj][2] == 0 || d[bi][bj][3] == 0)) { //要么人不能再走到新的格子了,要么箱子相邻的位置都已经能走到,则不需要继续处理
point p = Q2.front();
Q2.pop();
if (bi == p.i - 1 && bj == p.j && d[bi][bj][2] == 0) { //如果人走到了箱子的下侧
d[bi][bj][2] = step;
Q.push({ bi, bj, 2 });
}
if (bi == p.i && bj == p.j - 1 && d[bi][bj][3] == 0) { //如果人走到了箱子的右侧
d[bi][bj][3] = step;
Q.push({ bi, bj, 3 });
}
if (bi == p.i + 1 && bj == p.j && d[bi][bj][0] == 0) { //如果人走到了箱子的上侧
d[bi][bj][0] = step;
Q.push({ bi, bj, 0 });
}
if (bi == p.i && bj == p.j + 1 && d[bi][bj][1] == 0) { //如果人走到了箱子的左侧
d[bi][bj][1] = step;
Q.push({ bi, bj, 1 });
}
//注意 此时箱子也是障碍物(因为推箱子必须在外循环)
if (map[p.i - 1][p.j] != '#' && !(bi == p.i - 1 && bj == p.j) && !vis[p.i - 1][p.j]) { //人向上移动
Q2.push({ p.i - 1,p.j });
vis[p.i - 1][p.j] = true;
}
if (map[p.i][p.j - 1] != '#' && !(bi == p.i && bj == p.j - 1) && !vis[p.i][p.j - 1]) { //人向左移动
Q2.push({ p.i ,p.j - 1 });
vis[p.i][p.j - 1] = true;
}
if (map[p.i + 1][p.j] != '#' && !(bi == p.i + 1 && bj == p.j) && !vis[p.i + 1][p.j]) { //人向下移动
Q2.push({ p.i + 1,p.j });
vis[p.i + 1][p.j] = true;
}
if (map[p.i][p.j + 1] != '#' && !(bi == p.i && bj == p.j + 1) && !vis[p.i][p.j + 1]) { //人向右移动
Q2.push({ p.i ,p.j + 1 });
vis[p.i][p.j + 1] = true;
}
}
}
int main() {
int n, m, si, sj, bi, bj, ti, tj;
cin >> n >> m;
for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
cin >> map[i][j];
if (map[i][j] == 'T') {
ti = i;
tj = j;
}
else if (map[i][j] == 'B') {
bi = i;
bj = j;
}
else if (map[i][j] == 'S') {
si = i;
sj = j;
}
}
toNearBox(si, sj, bi, bj, 1); //先检查初始位置人能到箱子的那些位置
while (!Q.empty() && d[ti][tj][0] == 0 && d[ti][tj][1] == 0 && d[ti][tj][2] == 0 && d[ti][tj][3] == 0) { //如果箱子不能再移动了或者箱子以任意方式抵达了目标地点
point p = Q.front();
Q.pop();
if (p.p == 0 && map[p.i + 1][p.j] != '#') { //人在箱子上侧,箱子下移
d[p.i + 1][p.j][0] = d[p.i][p.j][0] + 1;
Q.push({ p.i + 1, p.j, 0}); //别忘了推的这个状态
toNearBox(p.i, p.j, p.i + 1, p.j, d[p.i + 1][p.j][0]); //检查人能移动到箱子的其他相邻位置
}
if (p.p == 1 && map[p.i][p.j + 1] != '#') { //人在箱子左侧,箱子右移
d[p.i][p.j + 1][1] = d[p.i][p.j][1] + 1;
Q.push({ p.i, p.j + 1, 1 });
toNearBox(p.i, p.j, p.i, p.j + 1, d[p.i][p.j + 1][1]);
}
if (p.p == 2 && map[p.i - 1][p.j] != '#') { //人在箱子下侧,箱子上移
d[p.i - 1][p.j][2] = d[p.i][p.j][2] + 1;
Q.push({ p.i - 1, p.j, 2 });
toNearBox(p.i, p.j, p.i - 1, p.j, d[p.i - 1][p.j][2]);
}
if (p.p == 3 && map[p.i][p.j - 1] != '#') { //人在箱子右侧,箱子左移
d[p.i][p.j - 1][3] = d[p.i][p.j][3] + 1;
Q.push({ p.i, p.j - 1, 3 });
toNearBox(p.i, p.j, p.i, p.j - 1, d[p.i][p.j - 1][3]);
}
}
//任意一个答案均可,因为是找到了答案就退出
if (d[ti][tj][0] != 0) cout << d[ti][tj][0] - 1;
else if (d[ti][tj][1] != 0)cout << d[ti][tj][1] - 1;
else if (d[ti][tj][2] != 0)cout << d[ti][tj][2] - 1;
else if (d[ti][tj][3] != 0)cout << d[ti][tj][3] - 1;
else cout << -1;
return 0;
}
评论:
请先登录,才能进行评论