链接:
武汉工程大学第三届ACM程序设计选拔赛B题
来源:牛客网
题面:
小明没有打过校赛但是他被拉去出题了。他非常想打校赛,但是他现在被困到了迷宫出题,现在请你帮小明逃离出题现场。该迷宫由n * m
个格子组成的迷宫,有些格子是陷阱,用’#‘表示,小明进入陷阱就会死亡,’.'表示没有陷阱。小明所在的位置用’S’表示,目的地用’T’表示。
小明只能向上下左右相邻的格子移动,每移动一次花费1秒。
有q个双向传送阵,每个传送阵各有两个口,都在迷宫的格子里,当走到或被传送到一个有传送阵的格子时,小明可以选择是否开启传送阵。如果开启传送阵,小明就会被传送到传送阵的另一端的格子里,这个过程会花费3秒;如果不开启传送阵,将不会发生任何事情,小明可以继续向上下左右四个方向移动。
一个格子可能既有多个传送阵,小明可以选择任意一个开启传送阵。使用传送阵是非常危险的,因为有的传送阵的另一端在陷阱里,如果小明使用这样的传送阵,那他就会死亡。请告诉小明活着逃离出题现场的最短时间。
比赛的时候死活没想出来是最短路,一直以为是道搜索题,赛后看了题解才恍然大悟(害,太菜了),本题主要是将二维压缩为一维,然后用dijkstra或者bellmen-ford跑一遍,最后判断是否可到达.
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define speed(x) ios::sync_with_stdio(false),cin.tie(x),cout.tie(x)
#define debug(x) cout<<#x<<'='<<x<<'\n';
using namespace std;
#define P pair<int,int>
const int MAX_N = 303;
const int mod = 1e9+9;
int n,m,q;
int d[MAX_N*MAX_N];
int gx[]={0,0,1,-1};
int gy[]={1,-1,0,0};
struct node{int to,cost;};
string s[MAX_N];
vector<node>edge[MAX_N*MAX_N];
bool used[MAX_N*MAX_N];
inline int nn(int i,int j){ return m*(i-1)+j;}
bool operator<(const node &a,const node &b){ return a.cost>b.cost;}
void addedge(int i,int j){
if(s[i-1][j-1]=='#') return;
for(int k=0;k<4;k++){
int nx=i+gx[k],ny=j+gy[k];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&s[nx-1][ny-1]!='#'){
int u=nn(i,j),v=nn(nx,ny);
edge[u].emplace_back(node{v,1});
edge[v].emplace_back(node{u,1});
}
}
}
int main(){
speed(nullptr);
cin>>n>>m>>q;
int S=0,T=0;
for(int i=0;i<n;i++){
cin>>s[i];
for(int j=0;j<s[i].size();j++){
if(s[i][j]=='S') S=nn(i+1,j+1);
if(s[i][j]=='T') T=nn(i+1,j+1);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
addedge(i,j);
d[nn(i,j)]=INF;
}
}
while(q-->0){
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
if(s[x1][y1]=='#'||s[x2][y2]=='#') continue;
edge[nn(x1+1,y1+1)].emplace_back(node{nn(x2+1,y2+1),3});
edge[nn(x2+1,y2+1)].emplace_back(node{nn(x1+1,y1+1),3});
}
priority_queue<node>q;
d[S]=0;
q.emplace(node{S,d[S]});
while(!q.empty()){
node e=q.top();
q.pop();
if(used[e.to]) continue;
used[e.to]=true;
for(auto [x,y]:edge[e.to]){
if(!used[x]&&d[x]>d[e.to]+y){
d[x]=d[e.to]+y;
q.emplace(node{x,d[x]});
}
}
}
cout<<(d[T]==INF?-1:d[T])<<'\n';
return 0;
}