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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;
#include <tr1/unordered_map>
#include <tr1/unordered_set>
using namespace tr1;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
const int INF = 1 << 29;
typedef long long ll;
typedef pair<int, int> pii;

int w, h;
inline bool get(ll S, int y, int x) { return S >> (y * w + x) & 1; }
inline ll bit(int y, int x) { return 1LL << (y * w + x); }
inline bool ok(ll S, int y, int x) {
  if (y < 0 || y >= h || x < 0 || x >= w)
    return 0;
  if (get(S, y, x))
    return 0;
  return 1;
}
const int dy[] = {-1, 0, 1, 0};
const int dx[] = {0, 1, 0, -1};

bool visited[7][7];
int sy, sx;
unordered_map<ll, int> mp[7][7];
bool dfs(ll S, int y, int x, int num) {
  //  if (num < 30) {
  // if (y) {
  if (mp[y][x].count(S))
    return 0;
  mp[y][x][S] = 1;
  // }
  //  }
  // cout << y << "," << x << "," << num << endl;
  // REP(i,h) {
  //   REP(j,w) cout << get(S,i,j);
  //   cout << endl;
  // }
  if (num == 0) {
    return abs(y - sy) + abs(x - sx) == 1;
  }
  // BFSして領域が2つあったらだめ
  {
    REP(i, h) REP(j, w) visited[i][j] = 0;
    REP(i, h) REP(j, w) {
      if (get(S, i, j))
        continue;
      queue<pii> Q;
      Q.push(pii(i, j));
      visited[i][j] = 1;
      int cnt = 0;
      while (!Q.empty()) {
        pii p = Q.front();
        Q.pop();
        ++cnt;
        REP(k, 4) {
          int ii = p.first + dy[k];
          int jj = p.second + dx[k];
          if (!ok(S, ii, jj))
            continue;
          if (visited[ii][jj])
            continue;
          visited[ii][jj] = 1;
          Q.push(pii(ii, jj));
        }
      }
      if (cnt != num)
        return 0;
      goto next;
    }
  next:;
  }
  {
    // 今の場所と最初の場所以外で凸の部分があったらだめ
    int cnt = 0;
    REP(i, h) REP(j, w) {
      if (get(S, i, j))
        continue;
      int c = 0;
      REP(k, 4) {
        int ii = i + dy[k];
        int jj = j + dx[k];
        if (!ok(S, ii, jj)) {
          if (ii != y || jj != x) {
            if (ii != sy || jj != sx) {
              ++c;
            }
          }
        }
      }
      if (c >= 3) {
        ++cnt;
      }
    }
    if (cnt >= 1)
      return 0;
  }
  REP(k, 4) {
    int yy = y + dy[k];
    int xx = x + dx[k];
    if (!ok(S, yy, xx))
      continue;
    if (dfs(S | bit(yy, xx), yy, xx, num - 1))
      return 1;
  }
  return 0;
}

int main() {
  while (cin >> w >> h, w || h) {
    ll S = 0;
    int num = 0;
    REP(i, h) REP(j, w) {
      int a;
      cin >> a;
      if (a)
        S |= bit(i, j);
      else {
        sy = i, sx = j;
        ++num;
      }
    }
    if (num <= 3) { // 空きマスが3以下
      puts("No");
      continue;
    }
    S |= bit(sy, sx);
    --num;
    REP(i, h) REP(j, w) mp[i][j].clear();
    cout << (dfs(S, sy, sx, num) ? "Yes" : "No") << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
const int INF = 1 << 29;
typedef long long ll;
typedef pair<int, int> pii;

int w, h;
inline bool get(ll S, int y, int x) { return S >> (y * w + x) & 1; }
inline ll bit(int y, int x) { return 1LL << (y * w + x); }
inline bool ok(ll S, int y, int x) {
  if (y < 0 || y >= h || x < 0 || x >= w)
    return 0;
  if (get(S, y, x))
    return 0;
  return 1;
}
const int dy[] = {-1, 0, 1, 0};
const int dx[] = {0, 1, 0, -1};

bool visited[7][7];
int sy, sx;
map<ll, int> mp[7][7];
bool dfs(ll S, int y, int x, int num) {
  //  if (num < 30) {
  // if (y) {
  //   if (mp[y][x].count(S)) return 0;
  //   mp[y][x][S] = 1;
  // }
  //  }
  // cout << y << "," << x << "," << num << endl;
  // REP(i,h) {
  //   REP(j,w) cout << get(S,i,j);
  //   cout << endl;
  // }
  if (num == 0) {
    return abs(y - sy) + abs(x - sx) == 1;
  }
  // BFSして領域が2つあったらだめ
  {
    REP(i, h) REP(j, w) visited[i][j] = 0;
    REP(i, h) REP(j, w) {
      if (get(S, i, j))
        continue;
      queue<pii> Q;
      Q.push(pii(i, j));
      visited[i][j] = 1;
      int cnt = 0;
      while (!Q.empty()) {
        pii p = Q.front();
        Q.pop();
        ++cnt;
        REP(k, 4) {
          int ii = p.first + dy[k];
          int jj = p.second + dx[k];
          if (!ok(S, ii, jj))
            continue;
          if (visited[ii][jj])
            continue;
          visited[ii][jj] = 1;
          Q.push(pii(ii, jj));
        }
      }
      if (cnt != num)
        return 0;
      goto next;
    }
  next:;
  }
  {
    // 今の場所と最初の場所以外で凸の部分があったらだめ
    int cnt = 0;
    REP(i, h) REP(j, w) {
      if (get(S, i, j))
        continue;
      int c = 0;
      REP(k, 4) {
        int ii = i + dy[k];
        int jj = j + dx[k];
        if (!ok(S, ii, jj)) {
          if (ii != y || jj != x) {
            if (ii != sy || jj != sx) {
              ++c;
            }
          }
        }
      }
      if (c >= 3) {
        ++cnt;
      }
    }
    if (cnt >= 1)
      return 0;
  }
  REP(k, 4) {
    int yy = y + dy[k];
    int xx = x + dx[k];
    if (!ok(S, yy, xx))
      continue;
    if (dfs(S | bit(yy, xx), yy, xx, num - 1))
      return 1;
  }
  return 0;
}

int main() {
  while (cin >> w >> h, w || h) {
    ll S = 0;
    int num = 0;
    REP(i, h) REP(j, w) {
      int a;
      cin >> a;
      if (a)
        S |= bit(i, j);
      else {
        sy = i, sx = j;
        ++num;
      }
    }
    if (num <= 3) { // 空きマスが3以下
      puts("No");
      continue;
    }
    S |= bit(sy, sx);
    --num;
    REP(i, h) REP(j, w) mp[i][j].clear();
    cout << (dfs(S, sy, sx, num) ? "Yes" : "No") << endl;
  }
}