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

#include <bits/stdc++.h>
using namespace std;

class Node {
private:
public:
  pair<int, int> point;
  int value = 0;
  int direction = 0;
  explicit Node(pair<int, int> p) { point = p; }
};

int cielK(int k, Node &node) {
  int value;
  if (node.value % k == 0) {
    value = node.value;
  } else {
    value = node.value - (node.value % k) + k;
  }
  return value;
}

int toHash(tuple<int, int, int> x, int w) {
  return get<0>(x) * w * 4 + get<1>(x) * 4 + get<2>(x);
}

int toHash(int x, int y, int d, int w) { return x * w * 4 + y * 4 + d; }

int main() {
  int h;
  int w;
  int k;
  cin >> h >> w >> k;

  pair<int, int> start;
  pair<int, int> goal;
  int x;
  int y;
  cin >> x >> y;
  start = make_pair(y - 1, x - 1);
  cin >> x >> y;
  goal = make_pair(y - 1, x - 1);

  set<pair<int, int>> leaves;
  for (int i = 0; i < h; i++) {
    string s;
    cin >> s;
    for (int j = 0; j < s.size(); j++) {
      auto point = make_pair(j, i);
      if ('@' == s.at(j)) {
        leaves.insert(point);
      }
    }
  }

  unordered_map<int, Node> nodes;
  Node startNode(start);
  auto node =
      nodes.insert({toHash(start.first, start.second, 0, w), startNode}).first;
  using mapIter = decltype(node);
  auto c = [](const mapIter &a, const mapIter &b) {
    return a->second.value > b->second.value;
  };
  priority_queue<mapIter, vector<mapIter>, decltype(c)> q(c);
  q.push(node);
  while (!q.empty()) {
    Node &node = q.top()->second;
    q.pop();

    tuple<int, int, int> front;
    bool canFront = true;
    if ((node.direction == 0) && (node.point.first - 1 >= 0) &&
        (leaves.find(make_pair(node.point.first - 1, node.point.second)) ==
         leaves.end())) {
      front = make_tuple(node.point.first - 1, node.point.second, 0);
    } else if ((node.direction == 1) && (node.point.first + 1 < w) &&
               (leaves.find(make_pair(node.point.first + 1,
                                      node.point.second)) == leaves.end())) {
      front = make_tuple(node.point.first + 1, node.point.second, 1);
    } else if ((node.direction == 2) && (node.point.second - 1 >= 0) &&
               (leaves.find(
                    make_pair(node.point.first, node.point.second - 1)) ==
                leaves.end())) {
      front = make_tuple(node.point.first, node.point.second - 1, 2);
    } else if ((node.direction == 3) && (node.point.second + 1 < h) &&
               (leaves.find(
                    make_pair(node.point.first, node.point.second + 1)) ==
                leaves.end())) {
      front = make_tuple(node.point.first, node.point.second + 1, 3);
    } else {
      canFront = false;
    }

    auto frontIt = nodes.find(toHash(front, w));
    if (canFront && frontIt == nodes.end()) {
      Node frontNode(make_pair(get<0>(front), get<1>(front)));
      frontNode.direction = get<2>(front);
      frontNode.value = node.value + 1;
      auto nodeIter = nodes.insert({toHash(front, w), frontNode}).first;
      q.push(nodeIter);
    } else if (canFront && frontIt->second.value > node.value + 1) {
      frontIt->second.value = node.value + 1;
    }

    tuple<int, int, int> turn;
    turn = make_tuple(node.point.first, node.point.second, 0);
    if (node.direction < 3) {
      get<2>(turn) = node.direction + 1;
    } else {
      get<2>(turn) = 0;
    }

    auto turnIt = nodes.find(toHash(turn, w));
    if (turnIt == nodes.end()) {
      Node turnNode(make_pair(get<0>(turn), get<1>(turn)));
      turnNode.direction = get<2>(turn);
      turnNode.value = cielK(k, node);
      auto nodeIter = nodes.insert({toHash(turn, w), turnNode}).first;
      q.push(nodeIter);
    } else if (turnIt->second.value > cielK(k, node)) {
      turnIt->second.value = cielK(k, node);
    }
  }

  /*
  for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
          auto nodeIter = nodes.find(toHash(j, i, 0, w));
          if (nodeIter == nodes.end()) {
              cout << "  @";
          }
          else {
              printf("%3d", nodeIter->second.value);
          }
      }
      cout << endl;
  }
  */

  auto goalIt = nodes.find(toHash(goal.first, goal.second, 0, w));
  if (goalIt != nodes.end()) {
    cout << cielK(k, goalIt->second) / k << endl;
  } else {
    cout << -1 << endl;
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

class Node {
private:
public:
  pair<int, int> point;
  int value = 0;
  int direction = 0;
  explicit Node(pair<int, int> p) { point = p; }
};

int cielK(int k, Node &node) {
  int value;
  if (node.value % k == 0) {
    value = node.value;
  } else {
    value = node.value - (node.value % k) + k;
  }
  return value;
}

int main() {
  int h;
  int w;
  int k;
  cin >> h >> w >> k;

  pair<int, int> start;
  pair<int, int> goal;
  int x;
  int y;
  cin >> x >> y;
  start = make_pair(y - 1, x - 1);
  cin >> x >> y;
  goal = make_pair(y - 1, x - 1);

  set<pair<int, int>> leaves;
  for (int i = 0; i < h; i++) {
    string s;
    cin >> s;
    for (int j = 0; j < s.size(); j++) {
      auto point = make_pair(j, i);
      if ('@' == s.at(j)) {
        leaves.insert(point);
      }
    }
  }

  map<tuple<int, int, int>, Node> nodes;
  Node startNode(start);
  auto node =
      nodes.insert({make_tuple(start.first, start.second, 0), startNode}).first;
  using mapIter = decltype(nodes)::iterator;
  auto c = [](const mapIter &a, const mapIter &b) {
    return a->second.value > b->second.value;
  };
  priority_queue<mapIter, vector<mapIter>, decltype(c)> q(c);
  q.push(node);
  while (!q.empty()) {
    Node &node = q.top()->second;
    q.pop();

    tuple<int, int, int> front;
    bool canFront = true;
    if ((node.direction == 0) && (node.point.first - 1 >= 0) &&
        (leaves.find(make_pair(node.point.first - 1, node.point.second)) ==
         leaves.end())) {
      front = make_tuple(node.point.first - 1, node.point.second, 0);
    } else if ((node.direction == 1) && (node.point.first + 1 < w) &&
               (leaves.find(make_pair(node.point.first + 1,
                                      node.point.second)) == leaves.end())) {
      front = make_tuple(node.point.first + 1, node.point.second, 1);
    } else if ((node.direction == 2) && (node.point.second - 1 >= 0) &&
               (leaves.find(
                    make_pair(node.point.first, node.point.second - 1)) ==
                leaves.end())) {
      front = make_tuple(node.point.first, node.point.second - 1, 2);
    } else if ((node.direction == 3) && (node.point.second + 1 < h) &&
               (leaves.find(
                    make_pair(node.point.first, node.point.second + 1)) ==
                leaves.end())) {
      front = make_tuple(node.point.first, node.point.second + 1, 3);
    } else {
      canFront = false;
    }

    auto frontIt = nodes.find(front);
    if (canFront && frontIt == nodes.end()) {
      Node frontNode(make_pair(get<0>(front), get<1>(front)));
      frontNode.direction = get<2>(front);
      frontNode.value = node.value + 1;
      auto nodeIter = nodes.insert({front, frontNode}).first;
      q.push(nodeIter);
    } else if (canFront && frontIt->second.value > node.value + 1) {
      frontIt->second.value = node.value + 1;
    }

    tuple<int, int, int> turn;
    turn = make_tuple(node.point.first, node.point.second, 0);
    if (node.direction < 3) {
      get<2>(turn) = node.direction + 1;
    } else {
      get<2>(turn) = 0;
    }

    auto turnIt = nodes.find(turn);
    if (turnIt == nodes.end()) {
      Node turnNode(make_pair(get<0>(turn), get<1>(turn)));
      turnNode.direction = get<2>(turn);
      turnNode.value = cielK(k, node);
      auto nodeIter = nodes.insert({turn, turnNode}).first;
      q.push(nodeIter);
    } else if (turnIt->second.value > cielK(k, node)) {
      turnIt->second.value = cielK(k, node);
    }
  }

  /*
  for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
          auto nodeIter = nodes.find(make_tuple(j, i, 0));
          if (nodeIter == nodes.end()) {
              cout << "  @";
          }
          else {
              printf("%3d", nodeIter->second.value);
          }
      }
      cout << endl;
  }
  */

  auto goalIt = nodes.find(make_tuple(goal.first, goal.second, 0));
  if (goalIt != nodes.end()) {
    cout << cielK(k, goalIt->second) / k << endl;
  } else {
    cout << -1 << endl;
  }

  return 0;
}