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

#include <climits>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <queue>
#include <utility>
#include <vector>
using namespace std;

// ori: 0 = 右向き, 1 = 下向き, 2 = 左向き, 3 = 上向き
struct state {
  int cost, x, y, ori;
  state(int c_, int x_, int y_, int ori_) : cost(c_), x(x_), y(y_), ori(ori_) {}
  bool operator>(const state &other) const { return cost > other.cost; }
};

template <class T> using Matrix = vector<vector<T>>;

int c[4];
int w, h;
// 右下左上
constexpr int dx[] = {1, 0, -1, 0};
constexpr int dy[] = {0, 1, 0, -1};

int dijkstra(const Matrix<int> &m) {
  priority_queue<state, vector<state>, greater<state>> q;
  q.push(state(0, 0, 0, 0));
  // d[x][y][(x, y)にいる時のロボットの向き]
  Matrix<vector<int>> d(w, vector<vector<int>>(h, vector<int>(4, INT_MAX)));
  d[0][0][0] = 0;

  while (!q.empty()) {
    state s = q.top();
    q.pop();

    if (s.x == w - 1 && s.y == h - 1)
      break;

    for (int ope = 0; ope < 4; ++ope) { // 全ての命令を行う
      int cost = 0;
      int ori = s.ori;
      if (ope != m[s.x][s.y])
        cost = c[ope];
      if (ope != 0) { // 向きを変える
        if (ope == 1)
          ori = (ori + 1) % 4; // 右折
        else if (ope == 2)
          ori = (ori + 2) % 4; // 反転
        else
          ori = (ori + 3) % 4; // 左折
      }
      int next_x = s.x + dx[ori];
      int next_y = s.y + dy[ori];
      if (next_x < 0 || next_x >= w)
        continue;
      if (next_y < 0 || next_y >= h)
        continue;
      if (d[next_x][next_y][ori] > d[s.x][s.y][s.ori] + cost) {
        d[next_x][next_y][ori] = d[s.x][s.y][s.ori] + cost;
        q.push(state(d[next_x][next_y][ori], next_x, next_y, ori));
      }
    }
  }

  int ans = INT_MAX;

  for (int e : d[w - 1][h - 1])
    ans = min(ans, e);

  return ans;
}

int main() {
  while (true) {
    cin >> w >> h;
    if (!w)
      break;
    Matrix<int> m(w, vector<int>(h));

    for (int i = 0; i < h; ++i)
      for (int j = 0; j < w; ++j)
        cin >> m[j][i];

    for (int i = 0; i < 4; ++i)
      cin >> c[i];

    cout << dijkstra(m) << endl;
  }

  return EXIT_SUCCESS;
}


Error: TLE

Fixed submission:

#include <climits>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <queue>
#include <utility>
#include <vector>
using namespace std;

// ori: 0 = 右向き, 1 = 下向き, 2 = 左向き, 3 = 上向き
struct state {
  int cost, x, y, ori;
  state(int c_, int x_, int y_, int ori_) : cost(c_), x(x_), y(y_), ori(ori_) {}
  bool operator<(const state &other) const { return cost < other.cost; }
};

template <class T> using Matrix = vector<vector<T>>;

int c[4];
int w, h;
// 右下左上
constexpr int dx[] = {1, 0, -1, 0};
constexpr int dy[] = {0, 1, 0, -1};

int dijkstra(const Matrix<int> &m) {
  priority_queue<state> q;
  q.push(state(0, 0, 0, 0));
  // d[x][y][(x, y)にいる時のロボットの向き]
  Matrix<vector<int>> d(w, vector<vector<int>>(h, vector<int>(4, INT_MAX)));
  d[0][0][0] = 0;

  while (!q.empty()) {
    state s = q.top();
    q.pop();

    if (s.x == w - 1 && s.y == h - 1)
      continue;

    for (int ope = 0; ope < 4; ++ope) { // 全ての命令を行う
      int cost = 0;
      int ori = s.ori;
      if (ope != m[s.x][s.y])
        cost = c[ope];
      if (ope != 0) { // 向きを変える
        if (ope == 1)
          ori = (ori + 1) % 4; // 右折
        else if (ope == 2)
          ori = (ori + 2) % 4; // 反転
        else
          ori = (ori + 3) % 4; // 左折
      }
      int next_x = s.x + dx[ori];
      int next_y = s.y + dy[ori];
      if (next_x < 0 || next_x >= w)
        continue;
      if (next_y < 0 || next_y >= h)
        continue;
      if (d[next_x][next_y][ori] > d[s.x][s.y][s.ori] + cost) {
        d[next_x][next_y][ori] = d[s.x][s.y][s.ori] + cost;
        q.push(state(d[next_x][next_y][ori], next_x, next_y, ori));
      }
    }
  }

  int ans = INT_MAX;

  for (int e : d[w - 1][h - 1])
    ans = min(ans, e);

  return ans;
}

int main() {
  while (true) {
    cin >> w >> h;
    if (!w)
      break;
    Matrix<int> m(w, vector<int>(h));

    for (int i = 0; i < h; ++i)
      for (int j = 0; j < w; ++j)
        cin >> m[j][i];

    for (int i = 0; i < 4; ++i)
      cin >> c[i];

    cout << dijkstra(m) << endl;
  }

  return EXIT_SUCCESS;
}