计蒜客 蒜头君回家(有条件的BFS)
计蒜客 蒜头君回家(有条件的BFS)
蒜头君要回家,但是他家的钥匙在他的朋友花椰妹手里,他要先从花椰妹手里取得钥匙才能回到家。花椰妹告诉他:“你家的钥匙被我复制了很多个,分别放在不同的地方。”
蒜头君希望能尽快回到家中,他需要首先取得任意一把钥匙,请你帮他计算出回家所需要的最短路程。
蒜头君生活的城市可以看做是一个 n×m 的网格,其中有道路有障碍,钥匙和家所在的地方可以看做是道路,可以通过。蒜头君可以在城市中沿着上下左右 4 个方向移动,移动一个格子算做走一步。
输入格式
第一行有两个整数 n,m。城市的地图是 n 行 m 列。(1≤n,m≤2000)
接下来的 n 行,每行 m 个字符,代表城市的地图。'.' 代表道路,'#' 代表障碍物,'S' 代表蒜头君所在的位置,'T' 代表蒜头家的位置,'P'代表钥匙的位置。除了障碍物以外,别的地方都可以通过。(题目保证蒜头君至少有一条路径可以顺利拿到钥匙并且回家)
输出格式
输出蒜头回家要走的最少步数,占一行。
样例输入
8 10 P.####.#P# ..#..#...# ..#T##.#.# .......... ..##.##### .......... #####...## ###....S##
样例输出
21
bfs 的时候标记数组多开一维度表示是否已经取得了钥匙的状态。如果到达终点并且取得钥匙的状态被标记,bfs 结束。
所以我们需要把vis数组开成三维,第三个维度来标记是否拿到钥匙,也就是同一个点其实可以走两次,第一次是没拿到钥匙的时候,第二次是拿到钥匙的时候
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 using namespace std; 5 6 int n,m; 7 char mat[2010][2010]; 8 bool vis[2010][2010][2]; 9 int dir[4][2]={1,0,-1,0,0,-1,0,1}; 10 11 struct node{ 12 int x,y,step,op; 13 node(){} 14 node(int _x,int _y,int _step,int _op):x(_x),y(_y),step(_step),op(_op){} 15 }st,key; 16 17 void bfs(node u) { 18 queue<node> q; 19 q.push(u); 20 vis[u.x][u.y][0]=1; 21 while(!q.empty()) { 22 node f=q.front(); 23 q.pop(); 24 printf("x=%d y=%d step=%d op=%d\n",f.x,f.y,f.step,f.op); 25 if(mat[f.x][f.y]=='T'&&f.op) { 26 printf("%d",f.step); 27 return ; 28 } 29 for(int i=0;i<4;i++) { 30 int nx=f.x+dir[i][0]; 31 int ny=f.y+dir[i][1]; 32 if(vis[nx][ny][f.op]||nx<0||nx>=n||ny<0||ny>=m||mat[nx][ny]=='#') continue; 33 if(mat[nx][ny]=='P') { 34 q.push(node(nx,ny,f.step+1,1)); 35 vis[nx][ny][1]=1; 36 } 37 else 38 { 39 q.push(node(nx,ny,f.step+1,f.op)); 40 vis[nx][ny][f.op]=1; 41 } 42 } 43 } 44 } 45 46 int main() { 47 scanf("%d%d",&n,&m); 48 for(int i=0;i<n;i++) { 49 scanf("%s",mat[i]); 50 for(int j=0;j<m;j++) { 51 if(mat[i][j]=='S') { 52 st.x=i; 53 st.y=j; 54 st.step=0; 55 st.op=0; 56 } 57 } 58 } 59 bfs(st); 60 return 0; 61 }
-