Problem p02579 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define INF 1001001001
typedef pair<int, int> P;

int main() {
  // 迷路を表す配列
  string maze[1005];
  int sx = 0, sy = 0; // スタート座標
  int gx = 0, gy = 0; // ゴール座標
  int d[1005][1005];  // 各位置への最短ワープ回数

  int dx[4] = {1, 0, 0, -1};
  int dy[4] = {0, 1, -1, 0};
  int ex[20] = {1, 1, -1, -1, 2,  2,  2,  2,  2,  1,
                1, 0, 0,  -1, -1, -2, -2, -2, -2, -2};
  int ey[20] = {1, -1, 1, -1, -2, -1, 0,  1, 2, -2,
                2, -2, 2, -2, 2,  -2, -1, 0, 1, 2};

  int x, y;
  cin >> x >> y;
  cin >> sx >> sy;
  sx--;
  sy--;
  cin >> gx >> gy;
  gx--;
  gy--;

  rep(i, x) { cin >> maze[i]; }

  rep(i, x) {
    rep(j, y) { d[i][j] = INF; }
  }

  queue<P> q;
  q.push(P(sx, sy)); // スタート位置
  d[sx][sy] = 0;
  int warp = 0;
  while (1) {
    int count = 0;
    set<P> r; // ワープ可能な位置
    while (q.size() > 0) {
      P p = q.front();
      q.pop();
      // ゴールなら探索をやめる
      // if(p.first==gx&&p.second==gy){
      //   cout << d[gx][gy];
      //   return 0;
      // }

      bool flag = false;
      rep(i, 4) {
        int nx = p.first + dx[i], ny = p.second + dy[i];
        // 訪れたことがないところにワープせずに移動可能
        //  cout << "(" << nx << "," << ny << ")";
        if (0 <= nx && nx <= x && 0 <= ny && ny <= y && maze[nx][ny] == '.' &&
            d[nx][ny] == INF) {
          d[nx][ny] = warp;
          q.push(P(nx, ny));
        }
      }
      rep(i, 20) {
        int nx = p.first + ex[i], ny = p.second + ey[i];
        // ワープ可能な位置として追加しておく
        if (0 <= nx && nx <= x && 0 <= ny && ny <= y && maze[nx][ny] == '.' &&
            d[nx][ny] == INF) {
          r.insert(P(nx, ny));
        }
      }
    }
    // ワープ可能な位置の計算
    warp++;
    for (auto pp : r) {
      if (d[pp.first][pp.second] == INF) {
        q.push(pp);
        d[pp.first][pp.second] = warp;
        // cout << "warp(" << pp.first << "," << pp.second << ")";
        count++;
      }
    }
    // cout << count;
    // ワープもできないしどこにも移動できない
    if (count == 0)
      break;
  }

  // rep(i, x){
  //   rep(j, y){
  //     if(d[i][j]==INF)cout << '#';
  //     else cout << d[i][j];
  //   }
  //   cout << endl;
  // }
  if (d[gx][gy] == INF)
    cout << "-1";
  else
    cout << d[gx][gy];

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define INF 1001001001
typedef pair<int, int> P;

int main() {
  // 迷路を表す配列
  string maze[1005];
  int sx = 0, sy = 0; // スタート座標
  int gx = 0, gy = 0; // ゴール座標
  int d[1005][1005];  // 各位置への最短ワープ回数

  int dx[4] = {1, 0, 0, -1};
  int dy[4] = {0, 1, -1, 0};
  int ex[20] = {1, 1, -1, -1, 2,  2,  2,  2,  2,  1,
                1, 0, 0,  -1, -1, -2, -2, -2, -2, -2};
  int ey[20] = {1, -1, 1, -1, -2, -1, 0,  1, 2, -2,
                2, -2, 2, -2, 2,  -2, -1, 0, 1, 2};

  int x, y;
  cin >> x >> y;
  cin >> sx >> sy;
  sx--;
  sy--;
  cin >> gx >> gy;
  gx--;
  gy--;

  rep(i, x) { cin >> maze[i]; }

  rep(i, x) {
    rep(j, y) { d[i][j] = INF; }
  }

  queue<P> q;
  set<P> r;          // ワープ可能な位置
  q.push(P(sx, sy)); // スタート位置
  d[sx][sy] = 0;
  int warp = 0;
  while (1) {
    int count = 0;
    while (q.size() > 0) {
      P p = q.front();
      q.pop();
      // ゴールなら探索をやめる
      // if(p.first==gx&&p.second==gy){
      //   cout << d[gx][gy];
      //   return 0;
      // }

      bool flag = false;
      rep(i, 4) {
        int nx = p.first + dx[i], ny = p.second + dy[i];
        // 訪れたことがないところにワープせずに移動可能
        //  cout << "(" << nx << "," << ny << ")";
        if (0 <= nx && nx <= x && 0 <= ny && ny <= y && maze[nx][ny] == '.' &&
            d[nx][ny] == INF) {
          d[nx][ny] = warp;
          q.push(P(nx, ny));
        }
      }
      rep(i, 20) {
        int nx = p.first + ex[i], ny = p.second + ey[i];
        // ワープ可能な位置として追加しておく
        if (0 <= nx && nx <= x && 0 <= ny && ny <= y && maze[nx][ny] == '.' &&
            d[nx][ny] == INF) {
          r.insert(P(nx, ny));
        }
      }
    }
    // ワープ可能な位置の計算
    warp++;
    for (auto pp : r) {
      if (d[pp.first][pp.second] == INF) {
        q.push(pp);
        d[pp.first][pp.second] = warp;
        // cout << "warp(" << pp.first << "," << pp.second << ")";
        count++;
      }
    }
    // cout << count;
    // ワープもできないしどこにも移動できない
    if (count == 0)
      break;
  }

  // rep(i, x){
  //   rep(j, y){
  //     if(d[i][j]==INF)cout << '#';
  //     else cout << d[i][j];
  //   }
  //   cout << endl;
  // }
  if (d[gx][gy] == INF)
    cout << "-1";
  else
    cout << d[gx][gy];

  return 0;
}