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

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <utility>
#include <vector>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
const double EPS = 1e-9;
const double PI = acos(-1.0);

struct node {
  vs f;
  pii pos;
  string hash;
  node(vs f, pii pos) : f(f), pos(pos) { hash = to_s(); }
  string to_s() const {
    if (hash != "") {
      return hash;
    }
    int n = f.size();
    string ret;
    REP(i, n) {
      REP(j, n) { ret += pos.first == i && pos.second == j ? '@' : f[i][j]; }
    }
    return ret;
  }
  bool operator<(const node &other) const { return hash < other.hash; }
};
int dy[] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dx[] = {-1, 0, 1, 1, 1, 0, -1, -1};

vs change(vs &f, int y, int x) {
  int n = f.size();
  vs nf(f);
  REP(i, n) {
    REP(j, n) {
      if (y == i && x == j)
        continue;
      int cnt = 0;
      REP(d, 8) {
        int yy = i + dy[d];
        int xx = j + dx[d];
        if (yy >= 0 && xx >= 0 && yy < n && xx < n) {
          cnt += f[yy][xx] == '#' || (y == yy && x == xx);
        }
      }
      switch (f[i][j]) {
      case '.':
        nf[i][j] = cnt == 3 ? '#' : '.';
        break;
      case '#':
        nf[i][j] = (cnt == 2 || cnt == 3 ? '#' : '.');
        break;
      default:
        assert(0);
      }
    }
  }
  return nf;
}

bool done(vs &f) {
  int n = f.size();
  REP(i, n) {
    REP(j, n) {
      if (f[i][j] == '#') {
        return false;
      }
    }
  }
  return true;
}

int main() {
  int N;
  while (cin >> N, N) {
    vs f(N);
    pii p;
    REP(i, N) {
      cin >> f[i];
      REP(j, N) {
        if (f[i][j] == '@') {
          p = make_pair(i, j);
          f[i][j] = '.';
        }
      }
    }
    queue<node> q;
    map<node, int> cost;
    q.push(node(f, p));
    cost[node(f, p)] = 0;
    int ans = -1;
    while (q.size()) {
      node n = q.front();
      q.pop();
      if (done(n.f)) {
        ans = cost[n];
        break;
      }
      REP(d, 8) {
        int y = n.pos.first + dy[d];
        int x = n.pos.second + dx[d];
        if (y >= 0 && x >= 0 && y < N && x < N) {
          if (n.f[y][x] == '.') {
            vs nf = change(n.f, y, x);
            node nnode(nf, make_pair(y, x));
            if (!EXIST(cost, nnode)) {
              cost[nnode] = cost[n] + 1;
              q.push(nnode);
            }
          }
        }
      }
    }
    cout << ans << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <utility>
#include <vector>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T> inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
const double EPS = 1e-9;
const double PI = acos(-1.0);

struct node {
  vs f;
  pii pos;
  node(vs f, pii pos) : f(f), pos(pos) {}
  string to_s() const {
    int n = f.size();
    string ret;
    REP(i, n) {
      REP(j, n) { ret += pos.first == i && pos.second == j ? '@' : f[i][j]; }
    }
    return ret;
  }
  bool operator<(const node &other) const { return to_s() < other.to_s(); }
};
int dy[] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dx[] = {-1, 0, 1, 1, 1, 0, -1, -1};

vs change(vs &f, int y, int x) {
  int n = f.size();
  vs nf(f);
  REP(i, n) {
    REP(j, n) {
      if (y == i && x == j)
        continue;
      int cnt = 0;
      REP(d, 8) {
        int yy = i + dy[d];
        int xx = j + dx[d];
        if (yy >= 0 && xx >= 0 && yy < n && xx < n) {
          cnt += f[yy][xx] == '#' || (y == yy && x == xx);
        }
      }
      switch (f[i][j]) {
      case '.':
        nf[i][j] = cnt == 3 ? '#' : '.';
        break;
      case '#':
        nf[i][j] = (cnt == 2 || cnt == 3 ? '#' : '.');
        break;
      default:
        assert(0);
      }
    }
  }
  return nf;
}

bool done(vs &f) {
  int n = f.size();
  REP(i, n) {
    REP(j, n) {
      if (f[i][j] == '#') {
        return false;
      }
    }
  }
  return true;
}

int main() {
  int N;
  while (cin >> N, N) {
    vs f(N);
    pii p;
    REP(i, N) {
      cin >> f[i];
      REP(j, N) {
        if (f[i][j] == '@') {
          p = make_pair(i, j);
          f[i][j] = '.';
        }
      }
    }
    queue<node> q;
    map<node, int> cost;
    q.push(node(f, p));
    cost[node(f, p)] = 0;
    int ans = -1;
    while (q.size()) {
      node n = q.front();
      q.pop();
      if (done(n.f)) {
        ans = cost[n];
        break;
      }
      REP(d, 8) {
        int y = n.pos.first + dy[d];
        int x = n.pos.second + dx[d];
        if (y >= 0 && x >= 0 && y < N && x < N) {
          if (n.f[y][x] == '.') {
            vs nf = change(n.f, y, x);
            node nnode(nf, make_pair(y, x));
            if (!EXIST(cost, nnode)) {
              cost[nnode] = cost[n] + 1;
              q.push(nnode);
            }
          }
        }
      }
    }
    cout << ans << endl;
  }
}