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

#include <algorithm>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

const int INF = INT_MAX / 4;

int h, w;
vector<string> s;

int main() {
  for (int d = 1;; ++d) {
    cin >> w >> h;
    if (h == 0)
      return 0;

    if (w == 1)
      swap(h, w);

    s.assign(h, string(w, ' '));
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        cin >> s[i][j];
      }
    }

    if (h == 1 && w == 1) {
      cout << "Case " << d << ": 0" << endl;
      continue;
    }

    vector<pair<int, int>> dp(1 << (2 * w + 2), make_pair(INF, -INF));
    for (int i = 0; i < (1 << w); ++i) {
      bitset<32> bs = i;
      int black = bs.count();
      bs <<= w;
      bs |= i;
      dp[bs.to_ulong()] = make_pair(black, black);
    }

    for (int y = 0; y < h; ++y) {
      for (int x = 0; x < w; ++x) {
        vector<pair<int, int>> next(1 << (2 * w + 2), make_pair(INF, -INF));
        for (int a = 0; a < (1 << (2 * w + 2)); ++a) {
          if (dp[a].first == INF)
            continue;

          for (int b = 0; b < 2; ++b) {
            bitset<32> bs = a;
            bs <<= 1;
            bs |= b;
            if (y == h - 1 && (bs[0] ^ bs[w]))
              continue;

            bool ng = false;

            if (x == 1) { // 左端
              int black = 0;
              for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 2; ++j) {
                  if (bs[i * w + j])
                    black += j + 1;
                }
              }
              if ((black >= 5) ^ (s[y][x - 1] == '#'))
                ng = true;
            }

            if (x > 1) { // 中央
              int black = 0;
              for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                  if (bs[i * w + j])
                    ++black;
                }
              }
              if ((black >= 5) ^ (s[y][x - 1] == '#'))
                ng = true;
            }

            if (x == w - 1) { // 右端
              int black = 0;
              for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 2; ++j) {
                  if (bs[i * w + j])
                    black += 2 - j;
                }
              }
              if ((black >= 5) ^ (s[y][x] == '#'))
                ng = true;
            }

            if (!ng) {
              bs &= (1 << (2 * w + 2)) - 1;
              if (y < h - 1) {
                next[bs.to_ulong()].first =
                    min(next[bs.to_ulong()].first, dp[a].first + b);
                next[bs.to_ulong()].second =
                    max(next[bs.to_ulong()].second, dp[a].second + b);
              } else {
                next[bs.to_ulong()].first =
                    min(next[bs.to_ulong()].first, dp[a].first);
                next[bs.to_ulong()].second =
                    max(next[bs.to_ulong()].second, dp[a].second);
              }
            }
          }
        }
        dp.swap(next);
      }
    }

    int minBlack = INF;
    int maxBlack = -INF;
    for (int i = 0; i < (1 << (2 * w + 2)); ++i) {
      minBlack = min(minBlack, dp[i].first);
      maxBlack = max(maxBlack, dp[i].second);
    }

    if (minBlack == INF)
      cout << "Case " << d << ": Impossible" << endl;
    else
      cout << "Case " << d << ": " << (maxBlack - minBlack) << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

const int INF = INT_MAX / 4;

int h, w;
vector<string> s;

bool check(bitset<24> bs, int y) {
  for (int i = 0; i < w; ++i) {
    int black = 0;
    for (int j = 0; j < 3; ++j) {
      for (int k = -1; k <= 1; ++k) {
        if (bs[j * w + max(0, min(w - 1, i + k))])
          ++black;
      }
    }
    if ((black >= 5) ^ (s[y][i] == '#'))
      return false;
  }

  return true;
}

int main() {
  for (int d = 1;; ++d) {
    cin >> w >> h;
    if (h == 0)
      return 0;

    s.resize(h);
    for (int i = 0; i < h; ++i)
      cin >> s[i];

    map<int, pair<int, int>> curr;
    for (int i = 0; i < (1 << w); ++i) {
      bitset<24> bs = (i << w) | i;
      int black = bs.count() / 2;
      curr[bs.to_ulong()] = make_pair(black, black);
    }

    for (int y = 0; y < h; ++y) {
      map<int, pair<int, int>> next;
      for (map<int, pair<int, int>>::iterator it = curr.begin();
           it != curr.end(); ++it) {
        for (int i = 0; i < (1 << w); ++i) {
          if (y == h - 1 && i != (it->first & ((1 << w) - 1)))
            continue;

          bitset<24> bs = i;
          int add = 0;
          if (y < h - 1)
            add = bs.count();
          bs |= it->first << w;

          if (check(bs, y)) {
            bs &= (1 << (2 * w)) - 1;
            if (next.find(bs.to_ulong()) == next.end()) {
              next[bs.to_ulong()] =
                  make_pair(it->second.first + add, it->second.second + add);
            } else {
              next[bs.to_ulong()].first =
                  min(next[bs.to_ulong()].first, it->second.first + add);
              next[bs.to_ulong()].second =
                  max(next[bs.to_ulong()].second, it->second.second + add);
            }
          }
        }
      }
      curr.swap(next);
    }

    if (curr.empty()) {
      cout << "Case " << d << ": Impossible" << endl;
      continue;
    }

    int minBlack = INF;
    int maxBlack = -INF;
    for (map<int, pair<int, int>>::iterator it = curr.begin(); it != curr.end();
         ++it) {
      minBlack = min(minBlack, it->second.first);
      maxBlack = max(maxBlack, it->second.second);
    }
    int ret = maxBlack - minBlack;

    cout << "Case " << d << ": " << ret << endl;
  }
}