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

#include <bits/stdc++.h>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)

using namespace std;

const int IINF = INT_MAX;
const int MAX_W = 9;
typedef pair<int, int> ii;

int h, w;
int field[10][10], indice[10][10];
int dp[2][1 << ((MAX_W + 1) * 2)];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};

inline bool isValid(int x, int y) { return 0 <= x && x < w && 0 <= y && y < h; }

#define SET(bitmask, index, value)                                             \\
  (bitmask = ((bitmask & ~(1 << (2 * index)) & ~(1 << (2 * index + 1))) |      \\
              (value << (index * 2))))
#define GET(bitmask, x)                                                        \\
  (((bitmask >> (2 * x)) & 1) | (((bitmask >> (2 * x + 1)) & 1) << 1))
#define FIX(bitmask) ((bitmask << 2) & ((1 << (2 * (w + 1))) - 1))
#define STAR (field[y][x] == 2 || field[y][x] == 3)
#define update(x, v) ((x == -1) ? (x = v) : (x = min(x, v)))

void compute() {

  set<int> S;
  vector<int> state;
  rep(bitmask, (1 << ((w + 1) * 2))) {
    bool success = true;
    for (int i = 0; i < (w + 1) * 2; i += 2) {
      if (((bitmask >> i) & 1) && ((bitmask >> (i + 1)) & 1)) {
        success = false;
        break;
      }
    }
    if (success)
      state.push_back(bitmask), S.insert(bitmask);
  }
  memset(dp, -1, sizeof(dp));

  int _size = state.size();
  bool initter = true, phase = false;
  int mini = IINF;
  int encounter = 0;
  rep(y, h) {
    rep(x, w) {
      /*
      cout << x << "," << y << endl;
      rep(i,_size){
        if( dp[phase][state[i]] != -1 ) {
          bitset<12> BIT(state[i]);
          for(int j=0;j<12;j+=2){
            cout << BIT[j] << BIT[j+1] << " ";
          }
          cout << " = " << dp[phase][state[i]] << endl;
        }
      }
      */
      if (field[y][x] == 2 || field[y][x] == 3)
        ++encounter;
      if (initter)
        dp[phase][0] = 0;

      rep(i, _size) {
        int bitmask = state[i];

        if (dp[phase][bitmask] == -1)
          continue;
        bitset<12> bit(bitmask);

        assert(S.count(bitmask));
        // ?????????
        if (field[y][x] == 1) {
          int nbitmask = bitmask;
          SET(nbitmask, x, 0);
          if (x == w - 1)
            nbitmask = FIX(nbitmask);
          update(dp[!phase][nbitmask], dp[phase][bitmask]);
          continue;
        }

        int nbitmask;
        // 0 0
        if (!((GET(bitmask, x) == 0) && (GET(bitmask, (x + 1)) == 0)))
          goto Label1;
        if (STAR) {
          // x 0
          if (y + 1 < h && field[y + 1][x] != 1) {
            nbitmask = bitmask;
            SET(nbitmask, x, ((field[y][x] == 3) + 1));
            if (x == w - 1)
              nbitmask = FIX(nbitmask);

            update(dp[!phase][nbitmask], dp[phase][bitmask] + 1);
          }
          // 0 x
          if (x + 1 < w && field[y][x + 1] != 1) {
            nbitmask = bitmask;
            SET(nbitmask, (x + 1), ((field[y][x] == 3) + 1));

            if (x == w - 1)
              nbitmask = FIX(nbitmask);

            update(dp[!phase][nbitmask], dp[phase][bitmask] + 1);
          }
        } else {
          // x x
          if (x + 1 < w && y + 1 < h && field[y][x + 1] != 1 &&
              field[y + 1][x] != 1) {
            REP(color, 1, 3) {
              nbitmask = bitmask;
              SET(nbitmask, x, color);
              SET(nbitmask, (x + 1), color);
              if (x == w - 1)
                nbitmask = FIX(nbitmask);
              update(dp[!phase][nbitmask], (dp[phase][bitmask] + 1));
            }
          }
          // 0 0
          nbitmask = bitmask;
          SET(nbitmask, x, 0);
          SET(nbitmask, (x + 1), 0);
          if (x == w - 1)
            nbitmask = FIX(nbitmask);
          update(dp[!phase][nbitmask], dp[phase][bitmask]);
        }

        continue;
      Label1:;
        // x 0
        // 0 x
        int color;
        if (!((GET(bitmask, x) && (GET(bitmask, (x + 1)) == 0)) ||
              (GET(bitmask, (x + 1)) && (GET(bitmask, x) == 0))))
          goto Label2;
        color = GET(bitmask, x) | GET(bitmask, (x + 1));
        assert(color == 1 || color == 2);
        if (STAR) {
          // 0 0
          if (((color == 1) ? 2 : 3) == field[y][x]) {

            nbitmask = bitmask;
            SET(nbitmask, x, 0);
            SET(nbitmask, (x + 1), 0);
            if (x == w - 1)
              nbitmask = FIX(nbitmask);
            update(dp[!phase][nbitmask], dp[phase][bitmask] + 1);
          }
        } else {
          // x 0
          if (y + 1 < h && field[y + 1][x] != 1) {
            nbitmask = bitmask;
            SET(nbitmask, x, color);
            SET(nbitmask, (x + 1), 0);
            if (x == w - 1)
              nbitmask = FIX(nbitmask);

            update(dp[!phase][nbitmask], (dp[phase][bitmask] + 1));
          }

          // 0 x
          if (x + 1 < w && field[y][x + 1] != 1) {
            nbitmask = bitmask;
            SET(nbitmask, x, 0);
            SET(nbitmask, (x + 1), color);

            if (x == w - 1)
              nbitmask = FIX(nbitmask);
            update(dp[!phase][nbitmask], (dp[phase][bitmask] + 1));
          }
        }
        continue;
      Label2:;
        // x x
        if (!(GET(bitmask, x) && GET(bitmask, (x + 1))))
          goto Label3;
        if (GET(bitmask, x) != GET(bitmask, (x + 1)))
          goto Label3;

        color = GET(bitmask, x);
        assert(color);
        // assert( GET(bitmask,x) == GET(bitmask,(x+1)) );

        // 0 0
        if (!STAR) {
          nbitmask = bitmask;
          SET(nbitmask, x, 0);
          SET(nbitmask, (x + 1), 0);
          if (x == w - 1)
            nbitmask = FIX(nbitmask);
          update(dp[!phase][nbitmask], dp[phase][bitmask] + 1);
        }
      Label3:;
      }
      if (field[y][x] == 2 || field[y][x] == 3)
        initter = false;
      rep(i, _size) dp[phase][state[i]] = -1;
      if (encounter >= 4 && dp[!phase][0] != -1) {
        mini = min(mini, dp[!phase][0]);
      }
      phase = !phase;
    }
  }

  /*
  puts("final");
  rep(i,_size){
    if( dp[phase][state[i]] != -1 ) {
      bitset<12> BIT(state[i]);
      for(int j=0;j<12;j+=2){
        cout << BIT[j] << BIT[j+1] << " ";
      }
      cout << " = " << dp[phase][state[i]] << endl;
    }
  }
  */
  if (dp[phase][0] != -1)
    mini = min(mini, dp[phase][0]);
  if (mini != IINF)
    printf("%d\\n", mini - 2);
  else
    puts("0");
}

int main() {

  while (scanf("%d %d", &h, &w), h | w) {
    rep(i, h) rep(j, w) scanf("%d", &field[i][j]);
    compute();
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)

using namespace std;

const int IINF = INT_MAX;

int H, W, mini, field[10][10], prev[10][10], mindist[10][10], nfield[10][10],
    mindist2[10][10], m1[10][10], m2[10][10];
vector<int> sp[2];
bool visited[10][10];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
bool X[10], Y[10];

bool isValid(int x, int y) { return 0 <= x && x < W && 0 <= y && y < H; }

void simulate_min(int dist[10][10], int f[10][10], int s) {
  rep(i, H) rep(j, W) dist[i][j] = IINF;
  dist[s / W][s % W] = 0;
  deque<int> deq;
  deq.push_back(s);
  while (!deq.empty()) {
    int cur = deq.front();
    deq.pop_front();
    int x = cur % W, y = cur / W;
    if (x + y * W != s && f[y][x] == f[s / W][s % W])
      return;
    rep(i, 4) {
      int nx = x + dx[i], ny = y + dy[i];
      if (!isValid(nx, ny))
        continue;
      if (f[ny][nx] != 0 && f[ny][nx] != f[s / W][s % W])
        continue;
      if (dist[ny][nx] == IINF) {
        dist[ny][nx] = dist[y][x] + 1;
        deq.push_back(nx + ny * W);
      }
    }
  }
}

void dfs(int x, int y, int cost, int f[10][10], int ep, deque<int> &path, int F,
         int S, int prev) {

  if (cost >= mini)
    return;
  if (m2[sp[S][1] / W][sp[S][1] % W] + cost >= mini)
    return;

  if (x + y * W == ep) {
    rep(i, H) rep(j, W) nfield[i][j] = field[i][j];
    rep(i, path.size()) nfield[path[i] / W][path[i] % W] = 1;
    simulate_min(mindist2, nfield, sp[S][0]);
    if (mindist2[sp[S][1] / W][sp[S][1] % W] == IINF)
      return;
    mini =
        min(mini, (int)path.size() - 1 + mindist2[sp[S][1] / W][sp[S][1] % W]);
    return;
  }
  int cnt = 0;
  rep(i, 4) {
    int nx = x + dx[i], ny = y + dy[i];
    if (!isValid(nx, ny))
      continue;
    cnt += visited[ny][nx];
  }
  if (cnt >= 2)
    return;

  {
    rep(i, 4) {
      if (i == (prev + 2) % 4)
        continue;
      int nx = x, ny = y;
      nx += dx[i], ny += dy[i];
      if (!isValid(nx, ny))
        continue;
      if (f[ny][nx] != 0 && f[ny][nx] != f[ep / W][ep % W])
        continue;
      if (visited[ny][nx])
        continue;
      while (1) {
        nx += dx[i], ny += dy[i];
        if (!isValid(nx, ny))
          break;
        if (f[ny][nx] != 0 && f[ny][nx] != f[ep / W][ep % W])
          break;
        if (X[nx] || Y[ny])
          break;
        if (visited[ny][nx])
          return;
      }
    }
  }

  rep(i, 4) {
    if (i == (prev + 2) % 4)
      continue;
    int nx = x + dx[i], ny = y + dy[i];
    if (!isValid(nx, ny))
      continue;
    if (f[ny][nx] != 0 && f[ny][nx] != f[ep / W][ep % W])
      continue;
    if (visited[ny][nx])
      continue;
    visited[ny][nx] = true;
    path.push_back(nx + ny * W);
    dfs(nx, ny, cost + 1, f, ep, path, F, S, i);
    path.pop_back();
    visited[ny][nx] = false;
  }
}

int compute(int F, int S) {
  rep(i, H) rep(j, W) visited[i][j] = false;
  deque<int> path;
  path.push_back(sp[F][0]);
  visited[sp[F][0] / W][sp[F][0] % W] = true;
  simulate_min(m1, field, sp[F][0]);
  simulate_min(m2, field, sp[S][0]);
  dfs(sp[F][0] % W, sp[F][0] / W, 0, field, sp[F][1], path, F, S, -IINF);
}

bool check(int a) {
  int x = a % W, y = a / W;
  return 0 == x || W - 1 == x || 0 == y || H - 1 == y;
}

int main() {
  while (scanf("%d %d", &H, &W), H | W) {
    rep(i, 2) sp[i].clear();
    rep(i, 10) X[i] = Y[i] = false;
    int one = 0;
    rep(i, H) rep(j, W) {
      cin >> field[i][j];
      if (field[i][j] == 1)
        X[j] = true, Y[i] = true, one++;
      if (field[i][j] == 2)
        sp[0].push_back(j + i * W), X[j] = Y[i] = true;
      if (field[i][j] == 3)
        sp[1].push_back(j + i * W), X[j] = Y[i] = true;
    }
    mini = H * W - one;
    if (check(sp[0][1]) && check(sp[0][0]) && check(sp[1][1]) &&
        check(sp[1][0])) {
      vector<int> vec;
      for (int i = 0; i < W; i++)
        if (field[0][i] == 2 || field[0][i] == 3)
          vec.push_back(field[0][i]);
      for (int i = 1; i < H; i++)
        if (field[i][W - 1] == 2 || field[i][W - 1] == 3)
          vec.push_back(field[i][W - 1]);
      for (int i = W - 2; i >= 0; i--)
        if (field[H - 1][i] == 2 || field[H - 1][i] == 3)
          vec.push_back(field[H - 1][i]);
      for (int i = H - 2; i >= 1; i--)
        if (field[i][0] == 2 || field[i][0] == 3)
          vec.push_back(field[i][0]);
      assert(vec.size() == 4);
      if (!(vec[0] == vec[1] || vec[0] == vec[3])) {
        puts("0");
        continue;
      }
    }

    compute(0, 1);
    if (mini == IINF)
      puts("0");
    else
      printf("%d\\n", mini);
  }
  return 0;
}