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

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <vector>

// BEGIN CUT HERE
#ifdef _MSC_VER
#include <agents.h>
#endif
// END CUT HERE

#define FOR(i, a, b) for (int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) begin(v), end(v)
#define REV(v) rbegin(v), rend(v)
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define X first
#define Y second
#define f(x, y) ((y)*w + (x))

using namespace std;

typedef long long ll;
typedef pair<int, int> P;

const int INF = 1e9;
const int N = 12;
int ch[N][N];
int d[N * N][N * N];
int dp[1 << N][N * N];

int main() {
  int h, w;
  while (cin >> h >> w, h | w) {
    vector<int> v;
    rep(i, h) rep(j, w) {
      cin >> ch[i][j];
      if (ch[i][j])
        v.push_back(f(j, i));
    }

    int n = h * w, t = v.size();
    rep(i, n) rep(j, n) if (i != j) d[i][j] = INF;
    rep(i, h) rep(j, w) {
      rep(k, 2) {
        int nx = j + k, ny = i + !k;
        if (nx >= w || ny >= w)
          continue;
        d[f(j, i)][f(nx, ny)] = d[f(nx, ny)][f(j, i)] = 1;
      }
    }
    rep(i, n) rep(j, n) rep(k, n) d[j][k] = min(d[j][k], d[j][i] + d[i][k]);

    rep(i, 1 << t) rep(j, n) dp[i][j] = INF;
    rep(i, t) rep(j, n) dp[1 << i][j] = d[v[i]][j];
    rep(i, 1 << t) rep(p, n) rep(q, n) for (int j = i; j > 0; j = (j - 1) & i)
        dp[i][p] = min(dp[i][p], dp[i ^ j][q] + dp[j][q] + d[p][q]);

    int res = INF, all = (1 << t) - 1;
    rep(i, 1 << t) rep(p, n) res = min(res, dp[i][p] + dp[all ^ i][p]);

    if (res == INF)
      res = n;
    else
      ++res;

    cout << h * w - res << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <vector>

// BEGIN CUT HERE
#ifdef _MSC_VER
#include <agents.h>
#endif
// END CUT HERE

#define FOR(i, a, b) for (int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) begin(v), end(v)
#define REV(v) rbegin(v), rend(v)
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define X first
#define Y second

using namespace std;

typedef long long ll;
typedef pair<int, int> P;

const int INF = 1e9;
const int N = 15;
int ch[N][N];
int vis[N][N];
int type[N * 2];
vector<P> heart, edge;

struct UnionFind {
  vector<int> par;
  UnionFind(int n) {
    par.resize(n);
    for (int i = 0; i < n; ++i)
      par[i] = i;
  }
  int find(int x) {
    if (x == par[x])
      return x;
    return par[x] = find(par[x]);
  }
  void unite(int x, int y) { par[find(x)] = find(y); }
  bool same(int x, int y) { return find(x) == find(y); }
};

void connect(int ai, int aj, int k) {
  P &a = heart[ai], &b = heart[aj];
  switch (k) {
  case 0:
    vis[a.second][a.first] = 1;
    vis[b.second][b.first] = 1;
    break;
  case 1: // 上下->右
    for (int i = a.second; i <= b.second; ++i)
      vis[i][a.first] = 1;
    for (int i = b.second; i <= a.second; ++i)
      vis[i][a.first] = 1;
    for (int j = a.first; j <= b.first; ++j)
      vis[b.second][j] = 1;
    break;
  case 2: // 右->上下
    for (int j = a.first; j <= b.first; ++j)
      vis[a.second][j] = 1;
    for (int i = a.second; i <= b.second; ++i)
      vis[i][b.first] = 1;
    for (int i = b.second; i <= a.second; ++i)
      vis[i][b.first] = 1;
    break;
  }
}

int n, h, w;
int check() {
  UnionFind uf(n);
  rep(i, edge.size()) {
    if (type[i])
      uf.unite(edge[i].first, edge[i].second);
  }
  set<int> s;
  rep(i, n) s.insert(uf.find(i));
  if (s.size() != 1)
    return INF;

  MEMSET(vis, 0);
  rep(i, edge.size()) { connect(edge[i].first, edge[i].second, type[i]); }

  int cnt = 0;
  rep(i, h) rep(j, w) cnt += vis[i][j];

  return cnt;
}

int dfs(int m) {
  if (m < 0) {
    return check();
  }
  int res = INF;
  rep(i, 3) {
    type[m] = i;
    res = min(res, dfs(m - 1));
  }
  return res;
}

int main() {
  while (cin >> h >> w, h | w) {
    heart.clear();
    edge.clear();
    rep(i, h) rep(j, w) {
      cin >> ch[i][j];
      if (ch[i][j])
        heart.push_back(make_pair(j, i));
    }

    sort(ALL(heart));
    n = heart.size();
    if (n == 1) {
      cout << 0 << endl;
      continue;
    }
    rep(i, n) FOR(j, i + 1, n) edge.push_back(make_pair(i, j));

    cout << h * w - dfs(edge.size() - 1) << endl;
  }

  return 0;
}