题目描述:
小明来到一个由n x m个格子组成的迷宫,有些格子是陷阱,用'#'表示,小明进入陷阱就会死亡,'.'表示没有陷阱。小明所在的位置用'S'表示,目的地用'T'表示。
小明只能向上下左右相邻的格子移动,每移动一次花费1秒。
有q个单向传送阵,每个传送阵各有一个入口和一个出口,入口和出口都在迷宫的格子里,当走到或被传送到一个有传送阵入口的格子时,小明可以选择是否开启传送阵。如果开启传送阵,小明就会被传送到出口对应的格子里,这个过程会花费3秒;如果不开启传送阵,将不会发生任何事情,小明可以继续向上下左右四个方向移动。
一个格子可能既有多个入口,又有多个出口,小明可以选择任意一个入口开启传送阵。使用传送阵是非常危险的,因为有的传送阵的出口在陷阱里,如果小明使用这样的传送阵,那他就会死亡。也有一些传送阵的入口在陷阱里,这样的传送阵是没有用的,因为小明不能活着进入。请告诉小明活着到达目的地的最短时间。
题解:
这里与平时bfs不同的一点是,他可以进行传送,但是这个传送他耗费的时间是3s,跟普通移动是不一样的,所以可能存在花费时间长但是移动距离却不如普通移动的距离远的问题,所以这里我们就不可以用普通的队列来解决这个问题了,想一下bfs队列里面的思想,就是考花费时间短的在队列前面从而解决的问题,所以我们这里可以用到优先队列(按照其花费时间由小到大排序)。
还有一个问题是如何记录传送门呢?
我们可以开一个二维结构体来记录,如果对应的坐标有相应的结果,那么我们就可以把他直接传到对应的位置,耗时3s,在继续进行普通的走动。
要注意一点就是通过传送门传过去那一点你是不可以把他标记为false的,因为你不确定是不是普通的移动比他耗时还少。
/*Keep on going Never give up*/ #pragma GCC optimize(3,"Ofast","inline") #include <bits/stdc++.h> const int maxn = 310; const int MaxN = 0x3f3f3f3f; const int MinN = 0xc0c0c00c; typedef long long ll; const int mod = 100000000; using namespace std; char a[maxn][maxn]; bool visited[maxn][maxn]; int n,m,q; int mins=MaxN; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; struct wazxy{ int x,y,steps; wazxy(int a,int b,int c){x=a,y=b,steps=c;} bool operator < (const wazxy & a)const {return steps>a.steps;} }; struct door{ int x,y; }ma[maxn][maxn]; void init(){ memset(visited,false,sizeof(visited)); memset(a,-1,sizeof(a)); memset(ma,0,sizeof(ma)); mins=MaxN; } bool bfs(int x,int y){ priority_queue<wazxy> q; q.push(wazxy(x,y,0)); while(!q.empty()){ wazxy temp=q.top(); q.pop(); if(a[temp.x][temp.y]=='T'){ mins=temp.steps; return true; } if(ma[temp.x][temp.y].x!=0&&!visited[ma[temp.x][temp.y].x][ma[temp.x][temp.y].y]&&a[ma[temp.x][temp.y].x][ma[temp.x][temp.y].y]!='#'){ q.push(wazxy(ma[temp.x][temp.y].x,ma[temp.x][temp.y].y,temp.steps+3)); } for(int i=0;i<4;i++){ int nx=temp.x+dx[i]; int ny=temp.y+dy[i]; if(!visited[nx][ny]&&(a[nx][ny]=='.'||a[nx][ny]=='T')){ visited[nx][ny]=true; q.push(wazxy(nx,ny,temp.steps+1)); } } } return false; } int main() { while(cin>>n>>m>>q){ init(); for(int i=1;i<=n;i++){ scanf("%s",a[i]+1); } for(int i=0;i<q;i++){ int x,y,ex,ey; scanf("%d%d%d%d",&x,&y,&ex,&ey); x++,y++,ex++,ey++; ma[x][y].x=ex,ma[x][y].y=ey; } bool flag=false; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(a[i][j]=='S'){ if(bfs(i,j)) flag=true; } } } if(flag) cout<<mins<<endl; else cout<<-1<<endl; } }