题意
给了一个n * m的矩阵,让从起点走到终点的最小花费是多少。
有一些地点可以进行传送,不过需要花费的时间为3,其他的正常上下左右走花费的时间是1。

思路
挺简单的题。
就是找到起点的位置,对于当前队列头的点,去走四个方向是不是满足要求。
然后再看当前点是不是有传送门,看传送的地点是不是满足即可。
因为要求花费时间最优,边权不都是1,所以用优先队列去bfs即可
第一次到达终点的花费就是最小花费。
对于标记有一个细节
就是如果新的点是通过上下左右直接走到的,肯定可以标记掉,因为是附近的。
但如果是传送门过去的就不要标记,因为传送门过去的不一定最优。
比如从(x,y) 传送到(x,y+2) 传送门要花费3,如果标记掉了,那么就错了 因为直接走过去只需要花费2

当然了这个还是看个人写法。可以直接把满足的都丢尽队列内,第一次取到这个坐标的时候的标记掉这个位置,后面如果在取到这个左边就continue,这样方便点。

偷个懒,优先队列没用结构体存,直接优先队列套两个pair了

#include<bits/stdc++.h>
using namespace std;
char mp[305][305];
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
map<pair<int,int>,vector<pair<int,int>>> k;
bool vis[305][305];
int n,m,q;
bool check(int x,int y){

    if(x<0 || x>=n || y<0 || y>=m || vis[x][y] || mp[x][y]=='#') return 1;
    return 0;
}
void bfs(){

    int ex,ey;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(mp[i][j]=='S'){
                ex=i;ey=j;break;
            }
        }
    }
    priority_queue<pair<int,pair<int,int>>> q;
    q.push({0,{ex,ey}});
    vis[ex][ey]=1;
    while(!q.empty()){
        pair<int,pair<int,int>> now=q.top();
        int num=now.first;
        int x=now.second.first,y=now.second.second;
        if(mp[x][y]=='T'){
            cout<<-num<<endl;
            return ;
        }
        q.pop();
        for(int i=0;i<4;i++){
            int fx=x+dx[i],fy=y+dy[i];
            if(check(fx,fy)) continue;
            vis[fx][fy]=1;
            q.push({num-1,{fx,fy}});
        }
        for(auto it:k[{x,y}]){
            int fx=it.first,fy=it.second;
            if(check(fx,fy)) continue;
            q.push({num-3,{fx,fy}});
        }
    }
    cout<<-1<<endl;

}
int main(){
    while(cin>>n>>m>>q){

        for(int i=0;i<n;i++) cin>>mp[i];
        k.clear();
        memset(vis,0,sizeof vis);
        while(q--){
            int a,b,c,d;cin>>a>>b>>c>>d;
            k[{a,b}].push_back({c,d});
        }
        bfs();
    }
    return 0;
}