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

#include <bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

typedef pair<int, int> P;

enum Type {
  North,
  East,
  South,
  West,
};

struct State {
  State(int arg_row, int arg_col, Type arg_dir, P arg_cost) {
    row = arg_row;
    col = arg_col;
    dir = arg_dir;
    cost = arg_cost;
  }
  bool operator<(const struct State &arg) const { return cost > arg.cost; }
  int row, col;
  P cost;
  Type dir;
};

int H, W, K;
int start_row, start_col, goal_row, goal_col;
int diff_row[4] = {-1, 0, 0, 1}, diff_col[4] = {0, -1, 1, 0};
P ***info;
char **table;
bool **visited;
Type type_dir[4] = {North, West, East, South};

bool rangeCheck(int row, int col) {

  return row >= 0 && row <= H - 1 && col >= 0 && col <= W - 1;
}

void dfs(int row, int col) {

  for (int i = 0; i < 4; i++) {

    int next_row = row + diff_row[i];
    int next_col = col + diff_col[i];

    if (rangeCheck(next_row, next_col) == false ||
        table[next_row][next_col] == '@')
      continue;
    if (visited[next_row][next_col])
      continue;

    visited[next_row][next_col] = true;
    dfs(next_row, next_col);
  }
}

int main() {

  scanf("%d %d %d", &H, &W, &K);

  table = new char *[H];
  visited = new bool *[H];
  for (int row = 0; row < H; row++) {

    table[row] = new char[W + 1];
    visited[row] = new bool[W + 1];
    for (int col = 0; col < W; col++) {

      visited[row][col] = false;
    }
  }

  info = (P ***)malloc(sizeof(P **) * H);
  for (int row = 0; row < H; row++) {

    info[row] = (P **)malloc(sizeof(P *) * W);
    for (int col = 0; col < W; col++) {

      info[row][col] = (P *)malloc(sizeof(P) * 4);
      for (int a = 0; a < 4; a++) {

        info[row][col][a].first = BIG_NUM;
        info[row][col][a].second = BIG_NUM;
      }
    }
  }

  scanf("%d %d %d %d", &start_row, &start_col, &goal_row, &goal_col);
  start_col--;
  start_row--;
  goal_col--;
  goal_row--;

  for (int row = 0; row < H; row++) {

    scanf("%s", table[row]);
  }

  visited[start_row][start_col] = true;
  dfs(start_row, start_col);
  if (!visited[goal_row][goal_col]) {

    printf("-1\\n");
    return 0;
  }

  priority_queue<State> Q;

  for (int i = 0; i < 4; i++) {

    info[start_row][start_col][i].first = 1;
    info[start_row][start_col][i].second = 0;

    Q.push(State(start_row, start_col, type_dir[i], make_pair(1, 0)));
  }

  int next_row, next_col;
  Type next_dir;
  P next_cost;

  while (!Q.empty()) {

    // printf("row:%d col:%d dir:%d turn:%d
    // move:%d\\n",Q.top().row,Q.top().col,Q.top().dir,Q.top().num_turn,Q.top().num_move);

    if ((Q.top().cost > info[Q.top().row][Q.top().col][Q.top().dir])) {

      Q.pop();

    } else if (Q.top().row == goal_row && Q.top().col == goal_col) {

      printf("%d\\n", Q.top().cost.first);
      return 0;

    } else {

      // 向きを変える
      for (int i = 0; i < 4; i++) {

        next_dir = type_dir[i];

        if ((Q.top().dir == North && next_dir == South) ||
            (Q.top().dir == East && next_dir == West) ||
            (Q.top().dir == South && next_dir == North) ||
            (Q.top().dir == West && next_dir == East))
          continue;

        next_row = Q.top().row + diff_row[i];
        next_col = Q.top().col + diff_col[i];

        if (rangeCheck(next_row, next_col) &&
            table[next_row][next_col] != '@') {

          if (next_dir == Q.top().dir && Q.top().cost.second < K) {

            next_cost.first = Q.top().cost.first;
            next_cost.second = Q.top().cost.second + 1;

          } else {

            next_cost.first = Q.top().cost.first + 1;
            next_cost.second = 1;
          }

          if (info[next_row][next_col][next_dir] > next_cost) {

            info[next_row][next_col][next_dir] = next_cost;
            Q.push(State(next_row, next_col, next_dir, next_cost));
          }
        }
      }
      Q.pop();
    }
  }

  printf("-1\\n");

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

enum Type {
  North,
  East,
  South,
  West,
};

struct Info {
  int num_turn, num_move;
};

struct State {
  State(int arg_row, int arg_col, int arg_num_turn, int arg_num_move,
        Type arg_dir) {
    row = arg_row;
    col = arg_col;
    num_turn = arg_num_turn;
    num_move = arg_num_move;
    dir = arg_dir;
  }
  bool operator<(const struct State &arg) const {

    if (num_turn != arg.num_turn) {

      return num_turn > arg.num_turn;
    } else {

      return num_move > arg.num_move;
    }
  }
  int row, col, num_turn, num_move;
  Type dir;
};

int H, W, K;
int start_row, start_col, goal_row, goal_col;
int diff_row[4] = {-1, 0, 0, 1}, diff_col[4] = {0, -1, 1, 0};
Info ***info;
char **table;
bool **visited;
Type type_dir[4] = {North, West, East, South};

bool rangeCheck(int row, int col) {

  return row >= 0 && row <= H - 1 && col >= 0 && col <= W - 1;
}

void dfs(int row, int col) {

  for (int i = 0; i < 4; i++) {

    int next_row = row + diff_row[i];
    int next_col = col + diff_col[i];

    if (rangeCheck(next_row, next_col) == false ||
        table[next_row][next_col] == '@')
      continue;
    if (visited[next_row][next_col])
      continue;

    visited[next_row][next_col] = true;
    dfs(next_row, next_col);
  }
}

int main() {

  scanf("%d %d %d", &H, &W, &K);

  table = new char *[H];
  visited = new bool *[H];
  for (int row = 0; row < H; row++) {

    table[row] = new char[W + 1];
    visited[row] = new bool[W + 1];
    for (int col = 0; col < W; col++) {

      visited[row][col] = false;
    }
  }

  info = (Info ***)malloc(sizeof(Info **) * H);
  for (int row = 0; row < H; row++) {

    info[row] = (Info **)malloc(sizeof(Info *) * W);
    for (int col = 0; col < W; col++) {

      info[row][col] = (Info *)malloc(sizeof(Info) * 4);
      for (int a = 0; a < 4; a++) {

        info[row][col][a].num_turn = BIG_NUM;
      }
    }
  }

  scanf("%d %d %d %d", &start_row, &start_col, &goal_row, &goal_col);
  start_col--;
  start_row--;
  goal_col--;
  goal_row--;

  for (int row = 0; row < H; row++) {

    scanf("%s", table[row]);
  }

  visited[start_row][start_col] = true;
  dfs(start_row, start_col);
  if (!visited[goal_row][goal_col]) {

    printf("-1\\n");
    return 0;
  }

  priority_queue<State> Q;

  for (int i = 0; i < 4; i++) {

    info[start_row][start_col][i].num_turn = 1;
    info[start_row][start_col][i].num_move = 0;

    Q.push(State(start_row, start_col, 1, 0, type_dir[i]));
  }

  int next_row, next_col, next_turn, next_move;
  Type next_dir;

  while (!Q.empty()) {

    // printf("row:%d col:%d dir:%d turn:%d
    // move:%d\\n",Q.top().row,Q.top().col,Q.top().dir,Q.top().num_turn,Q.top().num_move);

    if ((Q.top().num_turn >
         info[Q.top().row][Q.top().col][Q.top().dir].num_turn) ||
        (Q.top().num_turn ==
             info[Q.top().row][Q.top().col][Q.top().dir].num_turn &&
         Q.top().num_move >
             info[Q.top().row][Q.top().col][Q.top().dir].num_move)) {

      Q.pop();

    } else if (Q.top().row == goal_row && Q.top().col == goal_col) {

      printf("%d\\n", Q.top().num_turn);
      return 0;

    } else {

      // 向きを変える
      for (int i = 0; i < 4; i++) {

        next_dir = type_dir[i];

        if ((Q.top().dir == North && next_dir == South) ||
            (Q.top().dir == East && next_dir == West) ||
            (Q.top().dir == South && next_dir == North) ||
            (Q.top().dir == West && next_dir == East))
          continue;

        next_row = Q.top().row + diff_row[i];
        next_col = Q.top().col + diff_col[i];

        if (rangeCheck(next_row, next_col) &&
            table[next_row][next_col] != '@') {

          if (next_dir == Q.top().dir && Q.top().num_move < K) {

            next_turn = Q.top().num_turn;
            next_move = Q.top().num_move + 1;

          } else {

            next_turn = Q.top().num_turn + 1;
            next_move = 1;
          }

          if ((info[next_row][next_col][next_dir].num_turn > next_turn) ||
              (info[next_row][next_col][next_dir].num_turn == next_turn &&
               info[next_row][next_col][next_dir].num_move < next_move)) {

            info[next_row][next_col][next_dir].num_turn = next_turn;
            info[next_row][next_col][next_dir].num_move = next_move;
            Q.push(State(next_row, next_col, next_turn, next_move, next_dir));
          }
        }
      }
      Q.pop();
    }
  }

  printf("-1\\n");

  return 0;
}