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

#include <bits/stdc++.h>

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define ALL(x) (x).begin(), (x).end()

using namespace std;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

using ll = long long;
using ld = long double;

const int INF = 1e9;
const ld eps = 1e-9, pi = acos(-1.0);

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

struct board {
  int b[16];
  int c;
  int m;
  int bl;
  int prev;
  board(int *v, int c, int m, int bl, int p) : c(c), m(m), bl(bl), prev(p) {
    REP(i, 16) b[i] = v[i];
  }
};

bool operator<(board b1, board b2) {
  return ((b1.c + b1.m > b2.c + b2.m) ? true : false);
}

int dist(int a, int b) { return abs(a % 4 - b % 4) + abs(a / 4 - b / 4); }

int main() {
  int org[16];
  int blank = 0;
  int cost = 0;
  priority_queue<board> pq;
  REP(i, 16) {
    cin >> org[i];
    org[i]--;
    if (org[i] == -1) {
      org[i] = 15;
      blank = i;
    } else
      cost += dist(org[i], i);
  }
  pq.push(board(org, cost, 0, blank, 100));
  int res = 100;
  board target = pq.top();
  while (true) {
    target = pq.top();
    pq.pop();
    if (target.c == 0) {
      res = target.m + target.c;
      break;
    }
    REP(i, 4) {
      if (abs(target.prev - i) == 2)
        continue;
      int c_x = target.bl % 4 + dx[i];
      int c_y = target.bl / 4 + dy[i];
      if (c_x < 0 || c_x > 3 || c_y < 0 || c_y > 3)
        continue;
      int cand = c_x + 4 * c_y;
      int d = dist(target.b[cand], target.bl) - dist(target.b[cand], cand);
      if (d > 1)
        continue;
      if (target.c + d + target.m + 1 > 45)
        continue;
      swap(target.b[cand], target.b[target.bl]);
      pq.push(board(target.b, target.c + d, target.m + 1, cand, i));
      swap(target.b[cand], target.b[target.bl]);
    }
  }
  cout << res << endl;
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define ALL(x) (x).begin(), (x).end()
const int INF = 1e9;

typedef unsigned long long ll;

using namespace std;
const int answer[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0};
const bool dir[16][4] = {
    {false, false, true, true},
    {true, false, true, true},
    {true, false, true, true},
    {true, false, true, false},
    {false, true, true, true},
    {true, true, true, true},
    {true, true, true, true},
    {true, true, true, false},
    {false, true, true, true},
    {true, true, true, true},
    {true, true, true, true},
    {true, true, true, false},
    {false, true, false, true},
    {true, true, false, true},
    {true, true, false, true},
    {true, true, false, false}}; /* left, up, down, right */
const int dist[16][16] = {{6, 5, 4, 3, 5, 4, 3, 2, 4, 3, 2, 1, 3, 2, 1, 0},
                          {0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6},
                          {1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4, 4, 3, 4, 5},
                          {2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3, 5, 4, 3, 4},
                          {3, 2, 1, 0, 4, 3, 2, 1, 5, 4, 3, 2, 6, 5, 4, 3},
                          {1, 2, 3, 4, 0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5},
                          {2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3, 3, 2, 3, 4},
                          {3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2, 4, 3, 2, 3},
                          {4, 3, 2, 1, 3, 2, 1, 0, 4, 3, 2, 1, 5, 4, 3, 2},
                          {2, 3, 4, 5, 1, 2, 3, 4, 0, 1, 2, 3, 1, 2, 3, 4},
                          {3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2, 2, 1, 2, 3},
                          {4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1, 3, 2, 1, 2},
                          {5, 4, 3, 2, 4, 3, 2, 1, 3, 2, 1, 0, 4, 3, 2, 1},
                          {3, 4, 5, 6, 2, 3, 4, 5, 1, 2, 3, 4, 0, 1, 2, 3},
                          {4, 3, 4, 5, 3, 2, 3, 4, 2, 1, 2, 3, 1, 0, 1, 2},
                          {5, 4, 3, 4, 4, 3, 2, 3, 3, 2, 1, 2, 2, 1, 0, 1}};
vector<int> original(16, 0);

class board;

priority_queue<board> pq;
vector<ll> searched[16][16][16][16][16];

class board {
public:
  int moves;
  int wrongs;
  int zero_place;
  int cost;
  char pre;
  vector<int> tiles;
  ll k;

  explicit board(vector<int> num, int move, char pr, ll id, int zp, int w) {
    wrongs = w;
    k = id;
    tiles = num;
    if (pr == 'a') {
      REP(i, 16) {
        if (i < 11)
          k += num[i + 5] * pow(16, i);
        if (num[i] == 0)
          zero_place = i;
        else
          wrongs += dist[num[i]][(answer[i] + 15) % 16];
      }
      searched[tiles[0]][tiles[1]][tiles[2]][tiles[3]][tiles[4]].push_back(k);
    } else {
      zero_place = zp;
      wrongs = w;
    }
    moves = move;
    cost = wrongs + moves;
    pre = pr;
  }

  void board_to_int(char p, int d) {
    ll new_k = k;
    int new_w = wrongs - dist[tiles[zero_place + d]][zero_place + d] +
                dist[tiles[zero_place + d]][zero_place];
    if (zero_place > 4)
      new_k += (tiles[zero_place + d] * pow(16, (zero_place - 5)));
    if (zero_place + d > 4)
      new_k -= (tiles[zero_place + d] * pow(16, (zero_place + d - 5)));
    swap(tiles[zero_place], tiles[zero_place + d]);
    for (int i =
             searched[tiles[0]][tiles[1]][tiles[2]][tiles[3]][tiles[4]].size();
         i > 0; i--)
      if (new_k ==
          searched[tiles[0]][tiles[1]][tiles[2]][tiles[3]][tiles[4]][i - 1]) {
        swap(tiles[zero_place], tiles[zero_place + d]);
        return;
      }
    pq.push(board(tiles, moves + 1, p, new_k, zero_place + d, new_w));
    searched[tiles[0]][tiles[1]][tiles[2]][tiles[3]][tiles[4]].push_back(new_k);
    swap(tiles[zero_place], tiles[zero_place + d]);
    return;
  }

  void move() {
    if (dir[zero_place][0] && pre != 'l')
      board_to_int('r', -1);
    if (dir[zero_place][1] && pre != 'u')
      board_to_int('d', -4);
    if (dir[zero_place][2] && pre != 'd')
      board_to_int('u', 4);
    if (dir[zero_place][3] && pre != 'r')
      board_to_int('l', 1);
  }
};

bool operator<(board b1, board b2) {
  return ((b1.cost > b2.cost) ? true : false);
}

int solve() {
  pq.push(board(original, 0, 'a', 0, 0, 0));
  while (1) {
    auto target = pq.top();
    if (target.wrongs == 0)
      return target.moves;
    pq.pop();
    target.move();
  }
}

int main() {
  REP(i, 16) cin >> original[i];
  int move = solve();
  cout << move << endl;
  return 0;
}