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

#include <cmath>
#include <iostream>
#include <map>
#include <queue>
using namespace std;

constexpr int n = 4;
const int n2 = n * n;

int MDT[n2][n2];

struct Puzzle {
public:
  int f[n2], space, MD;
  int cost;

  bool operator<(const Puzzle &p) const {
    for (int i = 0; i < n2; i++) {
      if (f[i] == p.f[i])
        continue;
      return f[i] < p.f[i];
    }

    return false;
  }

  int getAllMD() {
    int sum = 0;
    for (int i = 0; i < n2; i++) {
      if (f[i] == n2)
        continue;
      sum += MDT[f[i] - 1][i];
    }
    return sum;
  }
};

struct State {
public:
  vector<State> solve;
  Puzzle puzzle;
  int estimated;

  void print() {
    for (int i = 0; i < n2; i++) {
      cout << ((puzzle.f[i] == n2) ? 0 : puzzle.f[i]) << " ";
      if (i % n == n - 1)
        cout << endl;
    }
  }

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

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

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

int dfs(int limit, int cnt, State s, int before) {
  if (cnt == 0) {
    if (s.puzzle.MD == 0)
      return s.puzzle.cost;
    else
      return -1;
  }

  int sx = s.puzzle.space / n, sy = s.puzzle.space % n;

  for (int i = 0; i < 4; i++) {
    int nx = sx + dx[i], ny = sy + dy[i];
    if (nx < 0 || nx >= n || ny < 0 || ny >= n || before + i == 3)
      continue;

    Puzzle np = s.puzzle;
    np.MD -= MDT[nx * n + ny][np.f[nx * n + ny] - 1];
    np.MD += MDT[sx * n + sy][np.f[nx * n + ny] - 1];

    swap(np.f[nx * n + ny], np.f[sx * n + sy]);
    np.cost++;
    np.space = nx * n + ny;

    State next;
    next.puzzle = np;
    next.estimated = np.MD + np.cost;

    /*
    cout << "---------------" << endl;
    cout << "limit = " << limit << " ";
    cout << "cnt = " << cnt << " ";
    cout << "f(x) = " << next.estimated << endl;
    next.print();
    */

    if (next.estimated > limit)
      continue;

    int tmp = dfs(limit, cnt - 1, next, i);
    if (tmp != -1)
      return tmp;
  }
  return -1;
}

int IDA(Puzzle in) {
  constexpr int MAX = 100;

  State s;
  s.puzzle = in;
  s.puzzle.cost = 0;
  s.puzzle.MD = s.estimated = in.getAllMD();

  for (int i = s.estimated; i <= MAX; i++) {
    int ans = dfs(i, i, s, -10);
    if (ans != -1) {
      return ans;
    }
  }
  return -1;
}

int main() {
  for (int i = 0; i < n2; i++) {
    for (int j = 0; j < n2; j++) {
      MDT[i][j] = abs(i / n - j / n) + abs(i % n - j % n);
    }
  }

  Puzzle in;
  for (int i = 0; i < n2; i++) {
    cin >> in.f[i];
    if (in.f[i] == 0) {
      in.space = i;
      in.f[i] = n2;
    }
  }

  cout << IDA(in) << endl;

  return 0;
}


Error: TLE

Fixed submission:

#include <cmath>
#include <iostream>
#include <map>
#include <queue>
using namespace std;

constexpr int n = 3;
const int n2 = n * n;

int MDT[n2][n2];

struct Puzzle {
public:
  int f[n2], space, MD;
  int cost;

  bool operator<(const Puzzle &p) const {
    for (int i = 0; i < n2; i++) {
      if (f[i] == p.f[i])
        continue;
      return f[i] < p.f[i];
    }

    return false;
  }

  int getAllMD() {
    int sum = 0;
    for (int i = 0; i < n2; i++) {
      if (f[i] == n2)
        continue;
      sum += MDT[f[i] - 1][i];
    }
    return sum;
  }
};

struct State {
public:
  vector<State> solve;
  Puzzle puzzle;
  int estimated;

  void print() {
    for (int i = 0; i < n2; i++) {
      cout << ((puzzle.f[i] == n2) ? 0 : puzzle.f[i]) << " ";
      if (i % n == n - 1)
        cout << endl;
    }
  }

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

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

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

int dfs(int limit, int cnt, State s, int before) {
  if (cnt == 0) {
    if (s.puzzle.MD == 0)
      return s.puzzle.cost;
    else
      return -1;
  }

  int sx = s.puzzle.space / n, sy = s.puzzle.space % n;

  for (int i = 0; i < 4; i++) {
    int nx = sx + dx[i], ny = sy + dy[i];
    if (nx < 0 || nx >= n || ny < 0 || ny >= n || before + i == 3)
      continue;

    Puzzle np = s.puzzle;
    np.MD -= MDT[nx * n + ny][np.f[nx * n + ny] - 1];
    np.MD += MDT[sx * n + sy][np.f[nx * n + ny] - 1];

    swap(np.f[nx * n + ny], np.f[sx * n + sy]);
    np.cost++;
    np.space = nx * n + ny;

    State next;
    next.puzzle = np;
    next.estimated = np.MD + np.cost;

    /*
    cout << "---------------" << endl;
    cout << "limit = " << limit << " ";
    cout << "cnt = " << cnt << " ";
    cout << "f(x) = " << next.estimated << endl;
    next.print();
    */

    if (next.estimated > limit)
      continue;

    int tmp = dfs(limit, cnt - 1, next, i);
    if (tmp != -1)
      return tmp;
  }
  return -1;
}

int IDA(Puzzle in) {
  constexpr int MAX = 100;

  State s;
  s.puzzle = in;
  s.puzzle.cost = 0;
  s.puzzle.MD = s.estimated = in.getAllMD();

  for (int i = s.estimated; i <= MAX; i++) {
    int ans = dfs(i, i, s, -10);
    if (ans != -1) {
      return ans;
    }
  }
  return -1;
}

int main() {
  for (int i = 0; i < n2; i++) {
    for (int j = 0; j < n2; j++) {
      MDT[i][j] = abs(i / n - j / n) + abs(i % n - j % n);
    }
  }

  Puzzle in;
  for (int i = 0; i < n2; i++) {
    cin >> in.f[i];
    if (in.f[i] == 0) {
      in.space = i;
      in.f[i] = n2;
    }
  }

  cout << IDA(in) << endl;

  return 0;
}