样例输入
8 10
P.####.#P#
..#..#...#
..#T##.#.#
..........
..##.#####
..........
#####...##
###....S##
样例输出
21
方法1
bfs 的时候标记数组多开一维度表示是否已经取得了钥匙的状态。如果到达终点并且取得钥匙的状态被标记,bfs 结束。
#include<bits/stdc++.h>
using namespace std;
int n,m,sx,sy,ex,ey;
char mp[2005][2005];
bool vis[2005][2005][2];//第三维标记是否有钥匙,0:没有,1:有
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct Node{
int x,y;
int step;
bool flag;//当前状态是否拿到钥匙
};
void bfs(int x,int y){
queue<Node> q;
q.push({x,y,0,false});
vis[x][y][0]=true;
while(!q.empty()){
Node now=q.front();
q.pop();
if(mp[now.x][now.y]=='T'){
if(now.flag){
cout<<now.step<<endl;
break;
}
continue;
}
for(int i=0;i<4;i++){
int tx=now.x+dir[i][0];
int ty=now.y+dir[i][1];
if(!vis[tx][ty][now.flag]&&tx<n&&tx>=0&&ty<m&&ty>=0&&mp[tx][ty]!='#'){
vis[tx][ty][now.flag]=true;
if(mp[tx][ty]=='P'){
q.push({tx,ty,now.step+1,true});
}else {
q.push({tx,ty,now.step+1,now.flag});
}
}
}
}
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>mp[i];
}
bool f1=false,f2=false;
for(int i=0;i<n;i++){//找到起点的位置
for(int j=0;j<m;j++){
if(mp[i][j]=='S'){
sx=i;
sy=j;
f1=true;
}
}
}
bfs(sx,sy);
return 0;
}
方法2
这道题目是一个技巧题目,我们可以用同一个bfs搜索两次。第一次从当前位置S开始搜索到达所有点的最短路径,第二次从家T开始搜索到达所有点的最短路径。最后我们计算每一个P,计算出S到P加上T到P之和,这个代表找这把钥匙回家的最短路径。然后我们找出他们中最小的就可以了。
#include <cstdio>
2
#include <queue>
3
#include <cstring>
4
#include <algorithm>
5
using namespace std;
6
7
const int MAXN = 2010;
8
const int INF = 0x3f3f3f3f;
9
10
int n, m;
11
int vis[MAXN][MAXN];
12
int ret[2][MAXN][MAXN];
13
char a[MAXN][MAXN];
14
int xx[4] = {1,-1,0,0};
15
int yy[4] = {0,0,1,-1};
16
17
void bfs(int xxx, int yyy, int d) {
18
queue< pair<int, int> > q;
19
q.push(make_pair(xxx, yyy));
20
vis[xxx][yyy] = 1;
21
ret[d][xxx][yyy] = 0;
22
while(!q.empty()) {
23
int tx = q.front().first;
24
int ty = q.front().second;
25
q.pop();
26
for (int i = 0;i < 4; ++i) {
27
int x = tx + xx[i];
28
int y = ty + yy[i];
29
if (x >= 0 && x < n && y >= 0 && y < m && a[x][y] != '#' && !vis[x][y]) {
30
ret[d][x][y] = ret[d][tx][ty] + 1;
31
vis[x][y] = 1;
32
q.push(make_pair(x, y));
33
}
34
}
35
}
36
}
37
38
int main() {
39
freopen("home.in", "r", stdin);
40
freopen("home.out", "w", stdout);
41
queue< pair<int, int> > q;
42
scanf("%d %d", &n, &m);
43
memset(ret, INF, sizeof(ret));
44
memset(vis, 0, sizeof(vis));
45
int sx, sy;
46
int tx, ty;
47
for (int i = 0;i < n; ++i) {
48
scanf("%s", a[i]);
49
for (int j = 0;j < m; ++j) {
50
if (a[i][j] == 'P') {
51
q.push(make_pair(i, j));
52
} else if (a[i][j] == 'S') {
53
sx = i;
54
sy = j;
55
} else if (a[i][j] == 'T') {
56
tx = i;
57
ty = j;
58
}
59
}
60
}
61
bfs(sx, sy, 0);
62
memset(vis, 0, sizeof(vis));
63
bfs(tx, ty, 1);
64
int ans = INF;
65
while(!q.empty()) {
66
int x = q.front().first;
67
int y = q.front().second;
68
q.pop();
69
ans = min(ans, ret[0][x][y] + ret[1][x][y]);
70
}
71
printf("%d\n", ans);
72
}