链接:https://ac.nowcoder.com/acm/problem/15665 来源:牛客网

小明来到一个由n x m个格子组成的迷宫,有些格子是陷阱,用'#'表示,小明进入陷阱就会死亡,'.'表示没有陷阱。小明所在的位置用'S'表示,目的地用'T'表示。

小明只能向上下左右相邻的格子移动,每移动一次花费1秒。

有q个单向传送阵,每个传送阵各有一个入口和一个出口,入口和出口都在迷宫的格子里,当走到或被传送到一个有传送阵入口的格子时,小明可以选择是否开启传送阵。如果开启传送阵,小明就会被传送到出口对应的格子里,这个过程会花费3秒;如果不开启传送阵,将不会发生任何事情,小明可以继续向上下左右四个方向移动。

一个格子可能既有多个入口,又有多个出口,小明可以选择任意一个入口开启传送阵。使用传送阵是非常危险的,因为有的传送阵的出口在陷阱里,如果小明使用这样的传送阵,那他就会死亡。也有一些传送阵的入口在陷阱里,这样的传送阵是没有用的,因为小明不能活着进入。请告诉小明活着到达目的地的最短时间。

做法

调了一个晚上的水题(),如果没有传送阵,那么就是普通的bfs,但如果加了传送阵,我们就应该每次先选择步数小的先走,这样才能保证走到终点的步数最小,传送门可以拿map记录一下位置,注意要先把起始点的传送门放进队列。

或者我们可以不用优先队列,我们记录一下走到某个x y位置的最小步数,最后输出终点的步数就行。

//本题代码
#include<bits/stdc++.h>
#define endl "\n"
#define ll long long
//dont forget to check long long
struct node{
    int x,y,step;
   bool operator < (const node &t)const{
        return step>t.step;
    }
};
struct nd{
    int x,y;
}st,ed;
int n,m,qq;
char s[310][310];
std::map<int,int> mp;
std::priority_queue<node> q;
bool vis[310][310];
int d[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void bfs()
{
    q.push({st.x,st.y,0});
    if(mp[st.x*m+st.y]!=0)
    {
        int pos=mp[st.x*m+st.y];
        int x=pos/m;
        int y=pos%m;
        q.push((node){x,y,3});
    }
    while(!q.empty())
    {
        auto cur=q.top();
        q.pop();
         if(cur.x<0||cur.y<0||cur.x>=n||cur.y>=m||vis[cur.x][cur.y]||s[cur.x][cur.y]=='#') continue;
        vis[cur.x][cur.y]=true;
        //std::cout<<x<<" "<<y<<endl;
        if(cur.x==ed.x&&cur.y==ed.y)
        {
            std::cout<<cur.step<<endl;
            return ;
        }
        vis[cur.x][cur.y]=true;
         
        for(int i=0;i<4;i++)
        {
            int dx=cur.x+d[i][0];
            int dy=cur.y+d[i][1];
            q.push((node){dx,dy,cur.step+1});
        }
        if(mp[cur.x*m+cur.y]!=0)
        {
            int pos=mp[cur.x*m+cur.y];
            int x=pos/m;
            int y=pos%m;
            q.push((node){x,y,cur.step+3});
        }
       
    }
    std::cout<<-1<<endl;
}
void slove()
{
     
     while(std::cin>>n>>m>>qq)
     {
         while(!q.empty()) q.pop();
        mp.clear();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                std::cin>>s[i][j];
                if(s[i][j]=='S') 
                {
                    
                    st={i,j};
                    
                }
                if(s[i][j]=='T')
                {
                    ed={i,j};
                    //std::cout<<ex<<" "<<ey<<endl;
                }
                vis[i][j]=false;
                
            }
        }
        for(int i=1;i<=qq;i++)
        {
            int x1,y1,x2,y2;
            std::cin>>x1>>y1>>x2>>y2;
           mp[x1*m+y1]=(x2*m+y2);
        }
        
      bfs();
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    int T=1;
    //std::cin>>T;
    while(T--)
    {
        slove();
    }

    return 0;
}