- 题目描述
精通程序设计的 Applese 双写了一个游戏。
在这个游戏中,它被困在了一个 n×m 的迷宫中,它想要逃出这个迷宫。
在迷宫中,有一些方格是水池,只有当 Applese 处于水属性的时候才可以通过;有一些方格是岩浆,只有当 Applese 是火属性的时候可以通过;有一些方格是墙壁,无论如何都无法通过;另一些格子是空地(包括起点和终点),可以自由通过。
在一些空地上有神秘道具可以让 Applese 转换自己的属性(从水属性变为火属性或从火属性变为水属性,需要一个单位的时间)。
已知 Applese 在一个单位的时间内可以朝四个方向行走一格,且开始处于水属性,位于空地的道具拾取后只能在该处立即使用(或者不使用),且可以多次使用。求它走出迷宫需要的最少时间。- 输入描述:
第一行两个正整数 n, m 表示迷宫的大小。
接下来 n 行,每行长度为 m 的字符串。描述地图。
其中 ‘S’ 表示起点,‘T’ 表示终点,’.’ 表示空地,‘w’表示岩浆,’~‘表示水池,’@’ 表示道具,’#’表示障碍。
保证地图中的起点和终点只有一个,道具都位于空地。- 输出描述:
输出一个整数,表示 Applese 走出迷宫的最短时间。特别地,如果 Applese 走不出迷宫,输出 “-1”。- 输入
5 5
.w@…
.S#…
~w#…
.w…~
@w.~T- 输出
18
用bfs找到起点到达每一个点的时间,直到找到终点,如果能够到达终点就返回到达终点的时间,所有能够找到的点找到后仍未到达终点则返回-1.
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#define pi 3.1415926
#define mod 1000000007
using namespace std;
//typedef pair<int,int> Node;
typedef long long LL;
const int Max_n=105;
int n,m,sx,sy,ex,ey;
char a[Max_n][Max_n];
int vis[Max_n][Max_n][2];//0表示可通过水池,1表示可通过岩浆
int net[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
struct Node{
int x,y,status,time;
};
int bfs(){
memset(vis,0,sizeof(int));
queue<Node>q;
Node now;now.x=sx,now.y=sy,now.status=0,now.time=0;
q.push(now);
vis[sx][sy][0]=1;
while(q.size()){
Node node=q.front();q.pop();
//printf("\n%d %d %d %d\n",node.x,node.y,node.status,node.time);
if(ex==node.x&&ey==node.y) return node.time;//到达终点
for(int i=0;i<4;i++){//枚举四个方向
int tx=node.x+net[i][0];
int ty=node.y+net[i][1];
//越界或者是障碍或者此点此状态已经求过(注意越界条件)
if(tx<0||tx>=n||ty<0||ty>=m||vis[tx][ty][node.status]||a[tx][ty]=='#') continue;
if(node.status==0&&a[tx][ty]=='w') continue;//水状态的时候即将经过岩浆
if(node.status&&a[tx][ty]=='~') continue;//火状态即将经过水池
vis[tx][ty][node.status]=1;//以上都不是说明可经过进行标记
Node nt;nt.x=tx,nt.y=ty,nt.status=node.status,nt.time=node.time+1;
q.push(nt);//加入队列中继续寻找终点
if(a[tx][ty]=='T')//当前点的下一个点可到达终点
return node.time+1;
}
//当前可以变换属性,并且变换后的状态还未被求出来
if(a[node.x][node.y]=='@'&&vis[node.x][node.y][node.status^1]==0){
vis[node.x][node.y][node.status^1]=1;
Node now1;now1.x=node.x,now1.y=node.y,now1.status=node.status^1,now1.time=node.time+1;
//printf("\n%d %d %d %d\n",now1.x,now1.y,now1.status,now1.time);
q.push(now1);
}//注意这里是当前点的另外一种状态(属性变换花费时间为1)
}
return -1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%s",a[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(a[i][j]=='S'){//起点
sx=i;sy=j;
}
if(a[i][j]=='T'){//终点
ex=i;ey=j;
}
}
}
printf("%d\n",bfs());
return 0;
}