所谓带状态改变是指:在搜索到某个位置的时候,状态发生改变,继续计算步数。
给一个例题:
蒜头君要回家,但是他家的钥匙在他的朋友花椰妹手里,他要先从花椰妹手里取得钥匙才能回到家。花椰妹告诉他:“你家的钥匙被我复制了很多个,分别放在不同的地方。”
蒜头君希望能尽快回到家中,他需要首先取得任意一把钥匙,请你帮他计算出回家所需要的最短路程。
蒜头君生活的城市可以看做是一个 n imes mn×m的网格,其中有道路有障碍,钥匙和家所在的地方可以看做是道路,可以通过。蒜头君可以在城市中沿着上下左右 44 个方向移动,移动一个格子算做走一步。
输入格式
第一行有三个整数 nn,mm。城市的地图是 nn行 mm 列。(1 leq n,m leq 20001≤n,m≤2000)
接下来的 nn 行,每行 mm 个字符,代表城市的地图。'.'
代表道路,'#'
代表障碍物,'S'
代表蒜头君所在的位置,'T'
代表蒜头家的位置,'P'
代表钥匙的位置。除了障碍物以外,别的地方都可以通过。(题目保证蒜头君至少有一条路径可以顺利拿到钥匙并且回家)
输出格式
输出蒜头回家要走的最少步数,占一行。
样例输入
8 10 P.####.#P# ..#..#...# ..#T##.#.# .......... ..##.##### .......... #####...## ###....S##
样例输出
21
当拿到钥匙后,进入找家的状态,,,
方法:增加一个维度,用来记录处于哪个状态。
#include<bits/stdc++.h> using namespace std; char mat[2005][2005]; bool vis[2][2005][2005]; int dx[]={1,-1,0,0}; int dy[]={0,0,1,-1}; int n,m; struct Node { int x,y; int sta; int step; }; int bfs(Node s) { queue<Node> q; while(!q.empty()) q.pop(); q.push(s); while(!q.empty()) { Node now=q.front(); if(now.sta==1&&mat[now.x][now.y]=='T') return now.step; q.pop(); int nx,ny; //cout<<now.x<<" "<<now.y<<endl; for(int i=0;i<4;i++) { nx=now.x+dx[i]; ny=now.y+dy[i]; if(nx>=0&&nx<n&&ny>=0&&ny<m) { if(!vis[now.sta][nx][ny]&&mat[nx][ny]!='#') { Node next; next.x=nx; next.y=ny; next.step=now.step+1; if(mat[nx][ny]=='P'||now.sta==1) { next.sta=1; } else { next.sta=0; } vis[next.sta][nx][ny]=1; q.push(next); } } } } } int main() { cin>>n>>m; for(int i=0;i<n;i++) { scanf("%s",mat[i]); } Node s; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(mat[i][j]=='S') { s.x=i; s.y=j; s.sta=0; s.step=0; } } } memset(vis,0,sizeof(vis)); cout<<bfs(s)<<endl; return 0; }