Problem p00626 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

#define REP(i, a, b) for (int i = a; i < (int)b; i++)
#define rep(i, n) REP(i, 0, n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a)                                                               \
  { cout << #a << " = " << a << endl; }
template <class T1, class T2> inline bool minimize(T1 &a, T2 b) {
  return b < a && (a = b, 1);
}
template <class T1, class T2> inline bool maximize(T1 &a, T2 b) {
  return a < b && (a = b, 1);
}

typedef long long ll;
int const inf = 1 << 29;

typedef vector<int> vec;
typedef vector<vec> matrix;

typedef int weight;

weight OPT[1 << 20][40];

weight minimum_steiner_tree(const vector<int> &T, const matrix &g) {
  const int n = g.size();
  const int numT = T.size();
  if (numT <= 1)
    return 0;

  matrix d(g); // all-pair shortest
  for (int k = 0; k < n; ++k)
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n; ++j)
        d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

  for (int S = 0; S < (1 << numT); ++S)
    for (int x = 0; x < n; ++x)
      OPT[S][x] = inf;

  for (int p = 0; p < numT; ++p) // trivial case
    for (int q = 0; q < n; ++q)
      OPT[1 << p][q] = d[T[p]][q];

  for (int S = 1; S < (1 << numT); ++S) { // DP step
    if (!(S & (S - 1)))
      continue;
    for (int p = 0; p < n; ++p)
      for (int E = 0; E < S; ++E)
        if ((E | S) == S)
          OPT[S][p] = min(OPT[S][p], OPT[E][p] + OPT[S - E][p]);
    for (int p = 0; p < n; ++p)
      for (int q = 0; q < n; ++q)
        OPT[S][p] = min(OPT[S][p], OPT[S][q] + d[p][q]);
  }
  weight ans = inf;
  for (int S = 0; S < (1 << numT); ++S)
    for (int q = 0; q < n; ++q)
      ans = min(ans, OPT[S][q] + OPT[((1 << numT) - 1) - S][q]);
  return ans;
}

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};

template <class T> constexpr bool in_range(T y, T x, T H, T W) {
  return 0 <= y && y < H && 0 <= x && x < W;
}

int main() {

  for (int H, W; cin >> H >> W && (H | W);) {
    zero(OPT);
    matrix mat(H, vec(W));
    rep(i, H) rep(j, W) cin >> mat[i][j];

    vector<int> T;
    rep(i, H) rep(j, W) if (mat[i][j]) T.push_back(i * W + j);

    matrix mat2(H * W, vec(H * W, inf));

    rep(i, H) {
      rep(j, W) {
        mat2[i * W + j][i * W + j] = 0;
        rep(k, 4) {
          const int ni = i + dy[k], nj = j + dx[k];
          if (in_range(ni, nj, H, W)) {
            mat2[i * W + j][ni * W + nj] /*= mat2[ni*W+nj][i*W+j]*/ = 1;
          }
        }
      }
    }

    //    rep(i, H*W) rep(j, W)     printf("%10d%c", mat2[i][j], j < W-1 ? ' ' :
    //    '\n');

    int ms = minimum_steiner_tree(T, mat2);
    cout << H * W - (1 + ms) << endl;
  }

  return 0;
}

Fixed submission:
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

#define REP(i, a, b) for (int i = a; i < (int)b; i++)
#define rep(i, n) REP(i, 0, n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a)                                                               \
  { cout << #a << " = " << a << endl; }
template <class T1, class T2> inline bool minimize(T1 &a, T2 b) {
  return b < a && (a = b, 1);
}
template <class T1, class T2> inline bool maximize(T1 &a, T2 b) {
  return a < b && (a = b, 1);
}

typedef long long ll;
int const inf = 1 << 29;

typedef vector<int> vec;
typedef vector<vec> matrix;

typedef int weight;

weight OPT[1 << 7][12 * 12 + 10];

weight minimum_steiner_tree(const vector<int> &T, const matrix &g) {
  const int n = g.size();
  const int numT = T.size();
  if (numT <= 1)
    return 0;

  matrix d(g); // all-pair shortest
  for (int k = 0; k < n; ++k)
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n; ++j)
        d[i][j] = min(d[i][j], d[i][k] + d[k][j]);

  for (int S = 0; S < (1 << numT); ++S)
    for (int x = 0; x < n; ++x)
      OPT[S][x] = inf;

  for (int p = 0; p < numT; ++p) // trivial case
    for (int q = 0; q < n; ++q)
      OPT[1 << p][q] = d[T[p]][q];

  for (int S = 1; S < (1 << numT); ++S) { // DP step
    if (!(S & (S - 1)))
      continue;
    for (int p = 0; p < n; ++p)
      for (int E = 0; E < S; ++E)
        if ((E | S) == S)
          OPT[S][p] = min(OPT[S][p], OPT[E][p] + OPT[S - E][p]);
    for (int p = 0; p < n; ++p)
      for (int q = 0; q < n; ++q)
        OPT[S][p] = min(OPT[S][p], OPT[S][q] + d[p][q]);
  }
  weight ans = inf;
  for (int S = 0; S < (1 << numT); ++S)
    for (int q = 0; q < n; ++q)
      ans = min(ans, OPT[S][q] + OPT[((1 << numT) - 1) - S][q]);
  return ans;
}

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};

template <class T> constexpr bool in_range(T y, T x, T H, T W) {
  return 0 <= y && y < H && 0 <= x && x < W;
}

int main() {

  for (int H, W; cin >> H >> W && (H | W);) {
    zero(OPT);
    matrix mat(H, vec(W));
    rep(i, H) rep(j, W) cin >> mat[i][j];

    vector<int> T;
    rep(i, H) rep(j, W) if (mat[i][j]) T.push_back(i * W + j);

    matrix mat2(H * W, vec(H * W, inf));

    rep(i, H) {
      rep(j, W) {
        mat2[i * W + j][i * W + j] = 0;
        rep(k, 4) {
          const int ni = i + dy[k], nj = j + dx[k];
          if (in_range(ni, nj, H, W)) {
            mat2[i * W + j][ni * W + nj] /*= mat2[ni*W+nj][i*W+j]*/ = 1;
          }
        }
      }
    }

    //    rep(i, H*W) rep(j, W)     printf("%10d%c", mat2[i][j], j < W-1 ? ' ' :
    //    '\n');

    int ms = minimum_steiner_tree(T, mat2);
    cout << H * W - (1 + ms) << endl;
  }

  return 0;
}