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

#include <cstdio>
#include <ctime>
#include <iostream>
#include <map>
#include <string>
#include <tr1/unordered_map>
using namespace std;
tr1::unordered_map<unsigned long long, int> s;
inline int mabs(int x) {
  if (x < 0)
    return -x;
  return x;
}
inline void swap(char &a, char &b) {
  char tmp;
  tmp = a, a = b, b = tmp;
}
inline int mmin(int a, int b) {
  if (a < b)
    return a;
  return b;
}
// int
// pla[16][2]={{4,4},{1,1},{1,2},{1,3},{1,4},{2,1},{2,2},{2,3},{2,4},{3,1},{3,2},{3,3},{3,4},{4,1},{4,2},{4,3},};
unsigned long long nod[16];
unsigned long long to;
int val() {
  int ret = 0;
  for (int i = 0; i < 4; ++i)
    for (int j = 0; j < 4; ++j) {
      if (!nod[i * 4 + j])
        continue;
      ret += mabs(i - (nod[i * 4 + j] - 1) / 4) +
             mabs(j - (nod[i * 4 + j] - 1) % 4);
    }
  return ret;
}
int ans = 50, limit;
void dfs(int pos, int step) {
  if (step + val() >= ans || step + val() > limit)
    return;
  unsigned long long zt = 0;
  for (int i = 0; i < 16; i++)
    zt = (zt + (nod[i] << (i * 4)));
  if (s[zt] != 0 && s[zt] <= step)
    return;
  s[zt] = step;
  if (zt == to)
    ans = mmin(ans, step);
  else {
    if (pos < 12)
      swap(nod[pos], nod[pos + 4]), dfs(pos + 4, step + 1),
          swap(nod[pos], nod[pos + 4]);
    if (pos > 3)
      swap(nod[pos], nod[pos - 4]), dfs(pos - 4, step + 1),
          swap(nod[pos], nod[pos - 4]);
    if (pos % 4 != 0)
      swap(nod[pos], nod[pos - 1]), dfs(pos - 1, step + 1),
          swap(nod[pos], nod[pos - 1]);
    if (pos % 4 != 3)
      swap(nod[pos], nod[pos + 1]), dfs(pos + 1, step + 1),
          swap(nod[pos], nod[pos + 1]);
  }
}
int main() {
  unsigned long long tmp = 1;
  for (unsigned long long i = 0; i < 15; i++) {
    to = to + ((i + 1) << (i * 4));
  }
  int sta;
  for (int i = 0, tmp; i != 4; ++i)
    for (int j = 0; j != 4; ++j) {
      cin >> nod[i * 4 + j];
      if (!nod[i * 4 + j])
        sta = i * 4 + j;
    }
  int sav;
  for (int i = 0; i != 46; ++i) {
    s.clear();
    sav = ans;
    limit = i, dfs(sta, 0);
    if (ans < sav) {
      printf("%d\\n", i);
      break;
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <cstdio>
#include <ctime>
#include <iostream>
#include <map>
#include <string>
#include <tr1/unordered_map>
using namespace std;
tr1::unordered_map<unsigned long long, bool> s;
inline int mabs(int x) {
  if (x < 0)
    return -x;
  return x;
}
inline void swap(char &a, char &b) {
  char tmp;
  tmp = a, a = b, b = tmp;
}
inline int mmin(int a, int b) {
  if (a < b)
    return a;
  return b;
}
int pla[16][2] = {{1, 1}, {1, 2}, {1, 3}, {1, 4}, {2, 1}, {2, 2},
                  {2, 3}, {2, 4}, {3, 1}, {3, 2}, {3, 3}, {3, 4},
                  {4, 1}, {4, 2}, {4, 3}, {4, 4}};
unsigned long long nod[16];
unsigned long long to;
int val() {
  int ret = 0;
  for (int i = 1; i <= 4; ++i)
    for (int j = 1; j <= 4; ++j) {
      int now = pla[nod[i * j - 1]][0];
      ret += mabs(pla[now][0] - i) + mabs(pla[now][1] - j);
    }
  return ret / 2;
}
int ans = 46, limit;
void dfs(int pos, int step) {
  if (step + val() >= ans || step + val() >= limit)
    return;
  if (step == ans)
    return;
  unsigned long long zt = 0;
  for (int i = 0; i < 16; i++)
    zt += nod[i] << (i * 4);
  if (s[zt])
    return;
  s[zt] = 1;
  if (zt == to)
    ans = mmin(ans, step);
  else {
    if (pos < 12)
      swap(nod[pos], nod[pos + 4]), dfs(pos + 4, step + 1),
          swap(nod[pos], nod[pos + 4]);
    if (pos > 3)
      swap(nod[pos], nod[pos - 4]), dfs(pos - 4, step + 1),
          swap(nod[pos], nod[pos - 4]);
    if (pos != 0)
      swap(nod[pos], nod[pos - 1]), dfs(pos - 1, step + 1),
          swap(nod[pos], nod[pos - 1]);
    if (pos != 15)
      swap(nod[pos], nod[pos + 1]), dfs(pos + 1, step + 1),
          swap(nod[pos], nod[pos + 1]);
  }
}
int main() {
  unsigned long long tmp = 1;
  for (int i = 0; i < 15; i++) {
    to += (i + 1) * tmp;
    tmp <<= 4;
  }
  int sta;
  for (int i = 0, tmp; i != 4; ++i)
    for (int j = 0; j != 4; ++j) {
      cin >> tmp;
      nod[i * 4 + j] = tmp;
      if (!tmp)
        sta = i * 4 + j;
    }
  int sav;
  for (int i = 1; i != 46; ++i) {
    s.clear();
    sav = ans;
    limit = i, dfs(sta, 0);
    if (ans < sav)
      break;
  }
  cout << ans << endl;
  return 0;
}