Description

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

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

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

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

Solution

经典的bfs问题,但是多出了一个传送阵,能够花费3s的时间从入口到出口
于是不能用普通的bfs的队列去做,因为最快到达的不一定花费时间最短
那么我们可以考虑取一个优先队列,每次我们都取当前花费时间最短的点去更新
这样的话就能保证最快到达终点的点是时间最短的
另外要注意这里输入的坐标 是
习惯数组从1开始的同学记得先 ++, ++
传送阵的话可以用一个 来存
一开始要把起点(和起点的所有传送出口)都放进队里

Code

#include<bits/stdc++.h>

typedef long long ll;

using namespace std;

const ll mod = 1e9 + 7;
const int N = 2e5 + 5;

char maze[305][305];
int dist[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
struct node {
  int x, y, step;
  node(int _x = 0, int _y = 0, int _step = 0): x(_x), y(_y), step(_step){}
  bool operator < (const node &s) const {
    return step > s.step;
  }
};
int sx, sy, ex, ey, n, m, qu;
bool vis[305][305];
vector<pair<int, int> > G[305][305];

int bfs() {
  priority_queue<node> q;
  q.push(node(sx, sy, 0));
  for(int i = 0; i < G[sx][sy].size(); i++) {
    int lx = G[sx][sy][i].first, ly = G[sx][sy][i].second;
    if(!vis[lx][ly] && maze[lx][ly] != '#' && lx >= 1 && lx <= n && ly >= 1 && ly <= m) {
      q.push(node(lx, ly, 3));
    } 
  }
  while(!q.empty()) {
    node now = q.top();
    q.pop();
    if(vis[now.x][now.y]) continue;
    vis[now.x][now.y] = 1;
    //cout << now.x << ' ' << now.y << "\n";
    if(now.x == ex && now.y == ey) return now.step;
    for(int i = 0; i < 4; i++) {
      int xx = now.x + dist[i][0];
      int yy = now.y + dist[i][1];
      if(!vis[xx][yy] && maze[xx][yy] != '#' && xx >= 1 && xx <= n && yy >= 1 && yy <= m) {
        for(int j = 0; j < G[xx][yy].size(); j++) {
          int lx = G[xx][yy][j].first, ly = G[xx][yy][j].second;
          if(!vis[lx][ly] && maze[lx][ly] != '#' && lx >= 1 && lx <= n && ly >= 1 && ly <= m) {
            q.push(node(lx, ly, now.step + 4));
          } 
        }
        q.push(node(xx, yy, now.step + 1));
      }
    }
  }
  return -1;
}

int main() {
  ios::sync_with_stdio(false), cin.tie(nullptr);
  while(cin >> n >> m >> qu) {
    //cin >> n >> m >> qu;
    for(int i = 1; i <= n; i++) {
      for(int j = 1; j <= m; j++) {
        G[i][j].clear(), vis[i][j] = 0;
      }
    }
    for(int i = 1; i <= n; i++) {
      for(int j = 1; j <= m; j++) {
        cin >> maze[i][j];
        if(maze[i][j] == 'S') {
          sx = i, sy = j;
        }
        if(maze[i][j] == 'T') {
          ex = i, ey = j;
        }
      }
    }
    while(qu--) {
      int x1, y1, x2, y2;
      cin >> x1 >> y1 >> x2 >> y2;
      x1++, y1++, x2++, y2++;
      G[x1][y1].push_back({x2, y2});
    }
    cout << bfs() << "\n";
  }
  return 0;
}