这题非常经典,但经典不是我记录它的理由。这道题值得记录的地方在于花费一个单位时间进行属性转换这个操作。这一点实现方法很多,但要么写起来有些麻烦,要么写出来不那么明了,看过标程以后才恍然大悟,原来可以很简单的处理它:只需要在搜到它的时候把它当作一个正常点,在操作结束,准备取出下一个点之前,把停留在原地一个单位时间进行属性转换作为一个特殊情况判断,符合条件就入队,这样一来代码就变得简洁明了了。
代码如下
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int n,m;
char mp[maxn][maxn];
int dis[maxn][maxn][2];
struct node
{
int x,y,op;
node(int tx,int ty,int top):x(tx),y(ty),op(top){}
};
int d[4][2]={-1,0,1,0,0,1,0,-1};
int bfs(int x,int y)
{
memset(dis,-1,sizeof dis);
queue<node> q;
q.push(node(x,y,0));
dis[x][y][0]=0;
while(!q.empty())
{
node t=q.front();q.pop();
for(int i=0;i<4;i++)
{
int tx=t.x+d[i][0];
int ty=t.y+d[i][1];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&dis[tx][ty][t.op]==-1&&mp[tx][ty]!='#')
{
if(t.op==0&&mp[tx][ty]=='w')
continue;
if(t.op==1&&mp[tx][ty]=='~')
continue;
dis[tx][ty][t.op]=dis[t.x][t.y][t.op]+1;
if(mp[tx][ty]=='T')
return dis[tx][ty][t.op];
q.push(node(tx,ty,t.op));
}
}
if(mp[t.x][t.y]=='@'&&dis[t.x][t.y][t.op^1]==-1)
{
dis[t.x][t.y][t.op^1]=dis[t.x][t.y][t.op]+1;
q.push(node(t.x,t.y,t.op^1));
}
}
return -1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>(mp[i]+1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='S')
{
printf("%d\n",bfs(i,j));
}
}
}
return 0;
}