技巧
    优先队列   BFS
思路
    能走则走。 如果有更优选择就更新重走。
实现
import java.io.*;
import java.util.*;

public class Main {
    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

    static class Pos {
        int x;
        int y;
        int time;

        public Pos(int x, int y, int time) {
            this.x = x;
            this.y = y;
            this.time = time;
        }
    }

    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        // 符合规则的四个移动方向
        int[][] d = new int[][]{{0, -1}, {0, 1}, {1, 0}, {-1, 0}};
        while (true) {
            String nmq = br.readLine();
            if (nmq == null) {
                break;
            }
            String[] nmqStrArr = nmq.split(" ");
            int n = Integer.parseInt(nmqStrArr[0]), m = Integer.parseInt(nmqStrArr[1]), q = Integer.parseInt(nmqStrArr[2]);
            char[][] maze = new char[n][m];
            int[][] visit = new int[n][m];
            // 开始 结束 位置坐标
            int sx = 0, sy = 0;
            for (int r = 0; r < n; r++) {
                char[] mazeLine = br.readLine().toCharArray();
                for (int c = 0; c < m; c++) {
                    maze[r][c] = mazeLine[c];
                    visit[r][c] = Integer.MAX_VALUE;
                    if (maze[r][c] == 'S') {
                        sx = r;
                        sy = c;
                    } else if (maze[r][c] == '#') {
                        visit[r][c] = -1;
                    }
                }
            }
            // key: 输入位置  x y         val: 输出坐标 x1 y1
            Map<String, List<String>> qMap = new HashMap<>();
            for (int i = 0; i < q; i++) {
                String[] qStr = br.readLine().split(" ");
                // 两端有陷阱的传送没有意义
                if (maze[Integer.parseInt(qStr[0])][Integer.parseInt(qStr[1])] == '#'
                        || maze[Integer.parseInt(qStr[2])][Integer.parseInt(qStr[3])] == '#') {
                    continue;
                }
                String k = qStr[0] + " " + qStr[1];
                String v = qStr[2] + " " + qStr[3];
                if (!qMap.containsKey(k)) {
                    qMap.put(k, new ArrayList<>());
                }
                qMap.get(k).add(v);
            }

            int ans = -1;
            PriorityQueue<Pos> pq = new PriorityQueue<>(Comparator.comparingInt(o -> o.time));
            pq.add(new Pos(sx, sy, 0));
            visit[sx][sy] = 0;
            while (!pq.isEmpty()) {
                Pos poll = pq.poll();
                if (maze[poll.x][poll.y] == 'T') {
                    ans = poll.time;
                    break;
                }
                // 四个方向尝试
                for (int i = 0; i < 4; i++) {
                    int nx = poll.x + d[i][0];
                    int ny = poll.y + d[i][1];
                    if (nx < 0 || ny < 0 || nx >= n || ny >= m || visit[nx][ny] == -1 || poll.time + 1 >= visit[nx][ny]) {
                        continue;
                    }
                    pq.add(new Pos(nx, ny, poll.time + 1));
                    visit[nx][ny] = poll.time + 1;
                }

                // 传送
                String key = poll.x + " " + poll.y;
                if (qMap.containsKey(key)) {
                    List<String> out = qMap.get(key);
                    for (String o : out) {
                        String[] targetPos = o.split(" ");
                        int tx = Integer.parseInt(targetPos[0]);
                        int ty = Integer.parseInt(targetPos[1]);
                        if (poll.time + 3 >= visit[tx][ty]) {
                            continue;
                        }
                        pq.add(new Pos(tx, ty, 3 + poll.time));
                        visit[tx][ty] = poll.time + 3;
                    }
                }
            }
            out.println(ans);
        }
        out.flush();
    }
}