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

#include <bits/stdc++.h>
using namespace std;
struct cww {
  cww() {
    ios::sync_with_stdio(false);
    cin.tie(0);
  }
} star;
#define P(x) cout << (x) << "\\n"
#define p(x) cout << (x)
#define all(c) (c).begin(), (c).end()
#define rall(c) (c).rbegin(), (c).rend()
#define vv(type, c, m, n, i) vector<vector<type>> c(m, vector<type>(n, i))
#define rep(i, a, n) for (int i = (a), i##_len = (n); i < i##_len; ++i)
#define rrep(i, a, n) for (int i = (a), i##_len = (n); i > i##_len; --i)
#define len(x) ((int)(x).size())
#define mp make_pair
#define eb emplace_back
#define fi first
#define se second
#define chmax(a, b)                                                            \\
  if (a < b)                                                                   \\
  a = b
#define chmin(a, b)                                                            \\
  if (b < a)                                                                   \\
  a = b
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<double> vd;
typedef vector<long long> vll;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef pair<int, int> pii;
constexpr int dx[] = {1, 0, -1, 0};
constexpr int dy[] = {0, 1, 0, -1};
constexpr char dir[4] = {'r', 'u', 'l', 'd'};
#define N 4
#define N2 16
#define LIMIT 100
int MDT[N2][N2];
struct Puzzle {
  int f[N2];
  int space, MD;
};
Puzzle state;
int limit;
int path[LIMIT];
int getAllMD(Puzzle pz) {
  int sum = 0;
  rep(i, 0, N2) {
    if (pz.f[i] == N2)
      continue;
    sum += MDT[i][pz.f[i] - 1];
  }
  return sum;
}
bool isSolved() {
  rep(i, 0, N2) if (state.f[i] != i + 1) return false;
  return true;
}
bool dfs(int depth, int prev) {
  if (state.MD == 0)
    return true;
  if (depth + state.MD > limit)
    return false;
  int sx = state.space / N;
  int sy = state.space % N;
  Puzzle tmp;
  int tx, ty;
  rep(r, 0, 4) {
    tx = sx + dx[r];
    ty = sy + dy[r];
    if (tx < 0 || tx >= N || ty < 0 || ty >= N)
      continue;
    if (max(prev, r) - min(prev, r) == 2)
      continue;
    tmp = state;
    state.MD -= MDT[tx * N + ty][state.f[tx * N + ty] - 1];
    state.MD += MDT[sx * N + sy][state.f[tx * N + ty] - 1];
    swap(state.f[tx * N + ty], state.f[sx * N + sy]);
    state.space = tx * N + ty;
    if (dfs(depth + 1, r)) {
      path[depth] = r;
      return true;
    }
    state = tmp;
  }
  return false;
}
string iterative_deepening(Puzzle in) {
  in.MD = getAllMD(in);
  string ans = "";
  for (limit = in.MD; limit <= LIMIT; ++limit) {
    state = in;
    if (dfs(0, -100)) {
      ans = "";
      rep(i, 0, limit) ans += dir[path[i]];
      return ans;
    }
  }
  return "unsolvable";
}
int main() {
  rep(i, 0, N2) {
    rep(j, 0, N2) { MDT[i][j] = abs(i / N - j / N) + abs(i % N - j % N); }
  }
  Puzzle in;
  rep(i, 0, N2) {
    cin >> in.f[i];
    if (in.f[i] == 0) {
      in.f[i] = N2;
      in.space = i;
    }
  }
  P(len(iterative_deepening(in)));
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <array>
#include <cstdio>
#include <functional>
#include <iostream>
#include <list>
#include <numeric>
#include <queue>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#define _USE_MATH_DEFINES

#include <map>
#include <math.h>

#define SENTINEL 1000000001

#define min(a, b) (a) > (b) ? (b) : (a)
#define max(a, b) (a) > (b) ? (a) : (b)

using namespace std;

typedef pair<int, int> pii;

struct State {
  int puzzle[16];
  int depth;
  int evaluation;
  int prev;

  bool operator<(const State &s) const { return evaluation < s.evaluation; }

  bool operator>(const State &s) const { return evaluation > s.evaluation; }

  bool operator==(const State &s) const {
    for (int i = 0; i < 16; i++) {
      if (puzzle[i] != s.puzzle[i]) {
        return false;
      }
    }
    return true;
  }
};

struct OwnNode {
  int key[16];
  OwnNode *left;
  OwnNode *right;

  OwnNode() : left(nullptr), right(nullptr) {}
  OwnNode(int key[]) : OwnNode() {
    for (int i = 0; i < 16; i++) {
      this->key[i] = key[i];
    }
  }

  void insert(int nkey[]) {
    int i = 0;
    for (; i < 16; i++) {
      if (key[i] != nkey[i]) {
        break;
      }
    }
    if (i == 16) {
      return;
    }
    if (key[i] > nkey[i]) {
      if (left == nullptr) {
        left = new OwnNode(nkey);
      } else {
        left->insert(nkey);
      }
    } else {
      if (right == nullptr) {
        right = new OwnNode(nkey);
      } else {
        right->insert(nkey);
      }
    }
  }

  bool find(int fkey[]) {
    int i = 0;
    for (; i < 16; i++) {
      if (key[i] != fkey[i]) {
        break;
      }
    }
    if (i == 16) {
      return true;
    }
    if (key[i] > fkey[i]) {
      if (left == nullptr) {
        return false;
      } else {
        return left->find(fkey);
      }
    } else {
      if (right == nullptr) {
        return false;
      } else {
        return right->find(fkey);
      }
    }
  }

  void deleteAll() {
    if (left != nullptr) {
      left->deleteAll();
    } else {
      delete left;
      left = nullptr;
    }
    if (right != nullptr) {
      right->deleteAll();
    } else {
      delete right;
      right = nullptr;
    }
  }
};

State goal;

int heuristic(State &s) {
  int eva = 0;
  int pos1[16], pos2[16];
  for (int i = 0; i < 16; i++) {
    pos1[s.puzzle[i]] = i;
    pos2[goal.puzzle[i]] = i;
  }
  for (int i = 0; i < 16; i++) {
    if (s.puzzle[i] == 0) {
      continue;
    }
    int manhattan = 0;
    manhattan += abs(pos1[i] / 4 - pos2[i] / 4);
    manhattan += abs(pos1[i] % 4 - pos2[i] % 4);
    eva += manhattan;
  }
  return eva;
}

int solve(State start, int limit) {
  State ts = start;
  int mini = 100000;

  if (ts == goal) {
    return ts.depth;
  }

  int zeroi = -1;
  for (int i = 0; i < 16; i++) {
    if (ts.puzzle[i] == 0) {
      zeroi = i;
      break;
    }
  }

  if (ts.prev != 3 && zeroi <= 11) {
    State tts = ts;
    int t = tts.puzzle[zeroi];
    tts.puzzle[zeroi] = tts.puzzle[zeroi + 4];
    tts.puzzle[zeroi + 4] = t;
    tts.depth++;
    tts.prev = 0;
    tts.evaluation = heuristic(tts) + tts.depth;
    if (tts.evaluation <= limit) {
      int result = solve(tts, limit);
      if (result != -1) {
        mini = min(result, mini);
      }
    }
  }
  if (ts.prev != 1 && zeroi % 4 != 3) {
    State tts = ts;
    int t = tts.puzzle[zeroi];
    tts.puzzle[zeroi] = tts.puzzle[zeroi + 1];
    tts.puzzle[zeroi + 1] = t;
    tts.depth++;
    tts.prev = 2;
    tts.evaluation = heuristic(tts) + tts.depth;
    if (tts.evaluation <= limit) {
      int result = solve(tts, limit);
      if (result != -1) {
        mini = min(result, mini);
      }
    }
  }
  if (ts.prev != 2 && zeroi % 4 != 0) {
    State tts = ts;
    int t = tts.puzzle[zeroi];
    tts.puzzle[zeroi] = tts.puzzle[zeroi - 1];
    tts.puzzle[zeroi - 1] = t;
    tts.depth++;
    tts.prev = 1;
    tts.evaluation = heuristic(tts) + tts.depth;
    if (tts.evaluation <= limit) {
      int result = solve(tts, limit);
      if (result != -1) {
        mini = min(result, mini);
      }
    }
  }
  if (ts.prev != 0 && 4 <= zeroi) {
    State tts = ts;
    int t = tts.puzzle[zeroi];
    tts.puzzle[zeroi] = tts.puzzle[zeroi - 4];
    tts.puzzle[zeroi - 4] = t;
    tts.depth++;
    tts.evaluation = heuristic(tts) + tts.depth;
    tts.prev = 3;
    if (tts.evaluation <= limit) {
      int result = solve(tts, limit);
      if (result != -1) {
        mini = min(result, mini);
      }
    }
  }

  return mini;
}

int main() {
  State start;

  goal.depth = 0;
  goal.evaluation = 0;
  goal.prev = 0;
  for (int i = 0; i < 16; i++) {
    goal.puzzle[i] = (i + 1) % 16;
  }

  for (int i = 0; i < 16; i++) {
    int n;
    cin >> n;

    start.puzzle[i] = n;
  }

  start.depth = 0;
  start.evaluation = 0;
  start.prev = -1;

  int mini = 100000;
  for (int i = heuristic(start); i <= 100; i += 2) {
    int result = solve(start, i);
    if (result != 100000) {
      mini = min(mini, result);
    }
  }

  printf("%d\\n", mini);

  return 0;
}