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

#include <iostream>
using namespace std;

#define N 4

int goal[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0};

int adjacent[16][4] = {
    {1, 4, -1, -1},  {0, 2, 5, -1},   {1, 3, 6, -1},    {2, 7, -1, -1},
    {0, 5, 8, -1},   {1, 4, 6, 9},    {2, 5, 7, 10},    {3, 6, 11, -1},
    {4, 9, 12, -1},  {5, 8, 10, 13},  {6, 9, 11, 14},   {7, 10, 15, -1},
    {8, 13, -1, -1}, {9, 12, 14, -1}, {10, 13, 15, -1}, {11, 14, -1, -1},
};

int dist[16][16] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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}};

int board[16];

void print_board() {
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++)
      cout << board[i * N + j] << ", ";
  }
  cout << endl;
}

int calc_heuristic() {
  int dis_sum = 0;
  int x = 0;
  for (int i = 0; i < 16; i++) {
    x = board[i];
    if (x != 0)
      dis_sum += dist[x][i];
  }
  return dis_sum;
}

bool flag = true;

void ida_search(int limit, int step, int space, int prev_m) {
  if (flag) {
    step++;

    int adj, h;
    for (int i = 0; i < 4; i++) {
      adj = adjacent[space][i];
      if (adj == -1)
        break;
      if (board[adj] == prev_m)
        continue;

      board[space] = board[adj];
      board[adj] = 0;
      h = calc_heuristic();
      if (h == 0) {
        cout << step << endl;
        flag = false;
      } else if (h + step < limit)
        ida_search(limit, step, adj, board[space]);
      board[adj] = board[space];
      board[space] = 0;
    }
  }
}

int main(void) {

  int init_space = 0;

  int in_raw[4];
  for (int i = 0; i < N; i++) {
    cin >> in_raw[0] >> in_raw[1] >> in_raw[2] >> in_raw[3];

    for (int j = 0; j < N; j++) {
      board[i * N + j] = in_raw[j];
      if (in_raw[j] == 0)
        init_space = i * N + j;
    }
  }

  int limit = calc_heuristic();
  if (limit == 0) {
    cout << 0 << endl;
    flag = false;
  }

  while (flag) {
    ida_search(limit, 0, init_space, -1);
    limit += 2;
  }
}


Error: TLE

Fixed submission:

#include <iostream>
#include <set>
#include <string>
#include <vector>
using namespace std;

#define N 4

string goal("bcdefghijklmnopa");

int calc_heuristic(string state) {
  int count = 0;
  for (int i = 0; i < 15; i++)
    if (state[i] != goal[i])
      count++;
  return count;
}

int main(void) {

  vector<string> st_stk;
  vector<int> pos_stk;
  vector<set<string>> hash_stk;
  vector<int> step_stk;

  string state;
  int position;
  set<string> hash;
  int step;

  int in_raw[4];
  for (int i = 0; i < N; i++) {
    cin >> in_raw[0] >> in_raw[1] >> in_raw[2] >> in_raw[3];

    for (int j = 0; j < N; j++) {
      state += ('a' + in_raw[j]);
      if (in_raw[j] == 0)
        position = i * N + j;
    }
  }
  hash.insert(state);

  st_stk.push_back(state);
  pos_stk.push_back(position);
  hash_stk.push_back(hash);
  step_stk.push_back(0);

  int h;
  int limit = 45;

  while (pos_stk.size() != 0) {

    state = st_stk.back();
    position = pos_stk.back();
    hash = hash_stk.back();
    step = step_stk.back();

    st_stk.pop_back();
    pos_stk.pop_back();
    hash_stk.pop_back();
    step_stk.pop_back();

    step++;

    if (position + N < 16) {
      string child(state);
      child[position] = child[position + N];
      child[position + N] = 'a';
      h = calc_heuristic(child);
      if (h == 0) {
        limit = step;
        continue;
      } else if (h + step < limit && hash.find(child) == hash.end()) {
        st_stk.push_back(child);
        pos_stk.push_back(position + N);

        set<string> hash_tmp(hash);
        hash_tmp.insert(child);
        hash_stk.push_back(hash_tmp);

        step_stk.push_back(step);
      }
    }

    if (position - N >= 0) {
      string child(state);
      child[position] = child[position - N];
      child[position - N] = 'a';
      h = calc_heuristic(child);
      if (h == 0) {
        limit = step;
        continue;
      } else if (h + step < limit && hash.find(child) == hash.end()) {
        st_stk.push_back(child);
        pos_stk.push_back(position - N);

        set<string> hash_tmp(hash);
        hash_tmp.insert(child);
        hash_stk.push_back(hash_tmp);

        step_stk.push_back(step);
      }
    }

    if (position % N != N - 1) {
      string child(state);
      child[position] = child[position + 1];
      child[position + 1] = 'a';
      h = calc_heuristic(child);
      if (h == 0) {
        limit = step;
        continue;
      } else if (h + step < limit && hash.find(child) == hash.end()) {
        st_stk.push_back(child);
        pos_stk.push_back(position + 1);

        set<string> hash_tmp(hash);
        hash_tmp.insert(child);
        hash_stk.push_back(hash_tmp);

        step_stk.push_back(step);
      }
    }

    if (position % N != 0) {
      string child(state);
      child[position] = child[position - 1];
      child[position - 1] = 'a';
      h = calc_heuristic(child);
      if (h == 0) {
        limit = step;
        continue;
      } else if (h + step < limit && hash.find(child) == hash.end()) {
        st_stk.push_back(child);
        pos_stk.push_back(position - 1);

        set<string> hash_tmp(hash);
        hash_tmp.insert(child);
        hash_stk.push_back(hash_tmp);

        step_stk.push_back(step);
      }
    }
  }

  cout << limit << endl;
  return 0;
}