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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)

using namespace std;
typedef long long ll;

const int INF = 1000000000;
const int MOD = 1000000007;
const double EPS = 1e-8;

int main() {
  int H, W;
  while (cin >> H >> W) {
    vector<string> str(H);
    REP(i, H) cin >> str[i];

    const int MAXS = 1 << W;
    vector<int> dp(MAXS, -INF);
    dp[0] = 0;
    for (int y = 0; y < H; y++) {
      for (int x = 0; x < W; x++) {
        vector<int> next(MAXS, -INF);
        for (int s = 0; s < MAXS; s++)
          if (dp[s] >= 0) {
            int cu = __builtin_popcount(s >> x);             // count of upper
            int cl = __builtin_popcount(s & ((1 << x) - 1)); // count of lower
            assert(cu + cl == __builtin_popcount(s));

            if (cl + (W - 1 - x) >= str[y].size())
              next[s << 1 & (MAXS - 1)] =
                  max(next[s << 1 & (MAXS - 1)], dp[s]); // path through

            if (cl == str[y].size())
              continue;

            int add = 0;
            if (cl > 0 && str[y][cl] == str[y][cl - 1] && (s & 1)) {
              add += 2;
            }
            if (y > 0 && (s >> (W - 1) & 1) &&
                str[y - 1][str[y - 1].size() - cu] == str[y][cl]) {
              add += 2;
            }
            next[(s << 1 & (MAXS - 1)) | 1] =
                max(next[(s << 1 & (MAXS - 1)) | 1], dp[s] + add);
          }
        dp.swap(next);
      }
    }
    int ans = 0;
    for (int s = 0; s < MAXS; s++)
      ans = max(ans, dp[s]);
    cout << ans << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)

using namespace std;
typedef long long ll;

const int INF = 1000000000;
const int MOD = 1000000007;
const double EPS = 1e-8;

int main() {
  int H, W;
  while (cin >> H >> W) {
    vector<int> vs[17];
    for (int s = 0; s < 1 << W; s++) {
      vs[__builtin_popcount(s)].push_back(s);
    }
    vector<string> str(H + 1);
    static int dp[129][1 << 16] = {};
    int ans = 0;
    for (int y = 1; y <= H; y++) {
      cin >> str[y];
      for (auto bs : vs[str[y - 1].size()]) {
        char bgrid[16] = {};
        for (int x = 0, curr = 0; x < W; x++) {
          if (bs >> x & 1) {
            bgrid[x] = str[y - 1][curr++];
          }
          assert(x != W - 1 || curr == str[y - 1].size());
        }
        for (auto ns : vs[str[y].size()]) {
          char ngrid[16] = {};
          for (int x = 0, curr = 0; x < W; x++) {
            if (ns >> x & 1) {
              ngrid[x] = str[y][curr++];
            }
            assert(x != W - 1 || curr == str[y].size());
          }
          int add = 0;
          for (int x = 0; x < W; x++) {
            if (ngrid[x] && ngrid[x] == bgrid[x])
              add += 2;
            if (x < W - 1 && ngrid[x] && ngrid[x] == ngrid[x + 1])
              add += 2;
          }
          dp[y][ns] = max(dp[y][ns], dp[y - 1][bs] + add);
          ans = max(ans, dp[y][ns]);
        }
      }
    }
    cout << ans << endl;
  }
  return 0;
}