题目描述
精通程序设计的 Applese 双写了一个游戏。
在这个游戏中,它被困在了一个 n×m
的迷宫中,它想要逃出这个迷宫。
在迷宫中,有一些方格是水池,只有当 Applese 处于水属性的时候才可以通过;有一些方格是岩浆,只有当 Applese 是火属性的时候可以通过;有一些方格是墙壁,无论如何都无法通过;另一些格子是空地(包括起点和终点),可以自由通过。
在一些空地上有神秘道具可以让 Applese 转换自己的属性(从水属性变为火属性或从火属性变为水属性,需要一个单位的时间)。
已知 Applese 在一个单位的时间内可以朝四个方向行走一格,且开始处于水属性,位于空地的道具拾取后只能在该处立即使用(或者不使用),且可以多次使用。求它走出迷宫需要的最少时间。
输入描述:
第一行两个正整数 n, m 表示迷宫的大小。
接下来 n 行,每行长度为 m 的字符串。描述地图。
其中 'S' 表示起点,'T' 表示终点,'.' 表示空地,'w'表示岩浆,'~'表示水池,'@' 表示道具,'#'表示障碍。
保证地图中的起点和终点只有一个,道具都位于空地。
输出描述:
输出一个整数,表示 Applese 走出迷宫的最短时间。特别地,如果 Applese 走不出迷宫,输出 "-1"。
示例1
输入
5 5
.w@..
.S#..
~w#..
.w..~
@w.~T
输出
18
备注:
1≤n,m≤100
思路:求最短时间,典型的广搜,但这题多了一个水和火的状态,大佬说可以类似看成是3维空间,坐标x,y和状态;3维vis数组可以用于标记某一状态下走过的路径,如果状态不变,则走过的路径不要再重复走(妙呀!);注意要维护队列,使其保持时间的最小值(那个if的位置,把当前节点转换后的状态压入队列)。
代码:
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
struct node{
int x, y, t, state; //可以把题意考虑成三维空间,坐标【x】,【y】和状态【水、火】
}nod;
int dir[][2] = {-1,0,1,0,0,1,0,-1};
char mp[105][105];
bool vis[105][105][2]; //state不变,则不要再走已经走过的路径
queue <node> que;
int n, m;
int bfs(int x, int y)
{
nod.x = x, nod.y = y;
nod.state = 0, nod.t = 0; //水的状态为0
que.push(nod);
while(!que.empty()){
nod = que.front();
que. pop();
if(mp[nod.x][nod.y] == 'T')
return nod.t;
for(int i=0; i<4; ++i){
int tx = nod.x + dir[i][0], ty = nod.y + dir[i][1], tst = nod.state;
if(tx < n && ty < m && tx >= 0 && ty >= 0 && !vis[tx][ty][tst]) //border
if(mp[tx][ty]=='S' || mp[tx][ty]=='T' || mp[tx][ty]=='@' || mp[tx][ty]=='.' || (mp[tx][ty]=='w' && tst==1) || (mp[tx][ty]=='~' && tst==0)){
que.push(node{tx, ty, nod.t+1, tst}); //可缩短代码长度
vis[tx][ty][tst] = 1;
}
}
//下面的if不能放在for里面,要维护队列,保持时间是最小的、
//也不能在for里面把@分两种情况讨论,变换水火的状态会变化时间,+2,+1的差异会使时间不能保持最小
if(mp[nod.x][nod.y] == '@' && !vis[nod.x][nod.y][!nod.state]){ //转换当前点的状态
que.push(node{nod.x, nod.y, nod.t+1, !nod.state}); //把转换后的状态压入队列
vis[nod.x][nod.y][nod.state] = 1;
}
}
return -1;
}
int main()
{
int sx, sy;
while(~scanf("%d%d", &n, &m)){
memset(vis, 0, sizeof(vis));
while(!que.empty()) que.pop();
for(int i=0; i<n; ++i){
for(int j=0; j<m; ++j){
scanf(" %c", &mp[i][j]);
if(mp[i][j] == 'S')
sx = i, sy = j;
}
}
printf("%d\n", bfs(sx, sy));
}
return 0;
}
网友评论