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

#include <algorithm>
#include <iostream>
#include <map>
#include <vector>

using namespace std;

const int mod = 100000;

int H, W;
int dp[2][20000][3];
char field[21][21];
int num[101];
int cnt = 0;
map<int, int> m;
int sits[1000001];

int solve() {
  for (int i = H * W; i >= 0; i--) {
    int nxt = i % 2;
    int cur = (i + 1) % 2;
    for (int aa = 0; aa < cnt; aa++) {
      int s = sits[aa];
      for (int pc = 0; pc < 3; pc++) {
        int res = 0;
        if (i == H * W)
          res = 1;
        else {
          int curh = i / W;
          int curw = i % W;
          if (field[curh][curw] != '?') {
            if (!(field[curh][curw] == 'I' && ((s >> curw) & 1))) {
              int ns = s;
              if (field[curh][curw] == 'O' && curw - 1 >= 0 && pc == 0)
                ns |= (1 << (curw - 1));
              else
                ns &= ~(1 << (curw - 1));
              int nc = num[field[curh][curw]];
              if (curw + 1 == W)
                nc = 2;
              ns &= ~(1 << curw);
              if (m.find(ns) == m.end())
                res += 0;
              else {
                res += dp[cur][m[ns]][nc];
                res %= mod;
              }
            }
          } else {
            for (int cc = 0; cc < 3; cc++) {
              int ns = s;
              if (cc == 1 && curw - 1 >= 0 && pc == 0) {
                ns |= (1 << (curw - 1));
                int nc = cc;
                if (curw + 1 == W)
                  nc = 2;
                ns &= ~(1 << curw);
                if (m.find(ns) == m.end())
                  res += 0;
                else {
                  res += dp[cur][m[ns]][nc];
                  res %= mod;
                }
              } else if (!(cc == 2 && ((s >> curw) & 1))) {
                ns &= ~(1 << (curw - 1));
                ns &= ~(1 << (curw));
                int nc = cc;
                if (curw + 1 == W)
                  nc = 2;
                if (m.find(ns) == m.end())
                  res += 0;
                else {
                  res += dp[cur][m[ns]][nc];
                  res %= mod;
                }
              }
            }
          }
        }
        dp[nxt][aa][pc] = res % mod;
      }
    }
  }
  long long res = 1;
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      if (field[i][j] == '?') {
        res *= 3;
        res %= mod;
      }
  return (res - dp[0][m[0]][2] + mod) % mod;
}

void dfs(int s, int pos) {
  if (pos >= W - 1) {
    m[s] = cnt++;
    sits[cnt - 1] = s;
  } else {
    if ((s >> pos) & 1) {
      dfs(s, pos + 1);
    } else {
      int ns = s;
      dfs(s, pos + 1);
      ns |= (1 << pos);
      dfs(ns, pos + 2);
    }
  }
}

int main() {
  num['J'] = 0;
  num['O'] = 1;
  num['I'] = 2;
  cin >> H >> W;
  dfs(0, 0);
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      cin >> field[i][j];
  cout << solve() << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

const int mod = 100000;

int H, W;
int dp[2][1 << 20][3];
char field[21][21];
int num[101];

int solve() {
  num['J'] = 0;
  num['O'] = 1;
  num['I'] = 2;
  for (int i = H * W; i >= 0; i--) {
    int nxt = i % 2;
    int cur = (i + 1) % 2;
    for (int s = 0; s < (1 << W); s++) {
      for (int pc = 0; pc < 3; pc++) {
        int res = 0;
        if (i == H * W)
          res = 1;
        else {
          int curh = i / W;
          int curw = i % W;
          if (field[curh][curw] != '?') {
            if (field[curh][curw] == 'I' && ((s >> curw) & 1)) {
              res = 0;
            } else {
              int ns = s;
              if (field[curh][curw] == 'O' && curw - 1 >= 0 && pc == 0) {
                ns |= (1 << (curw - 1));
              } else
                ns &= ~(1 << (curw - 1));
              int nc = num[field[curh][curw]];
              if (curw + 1 == W)
                nc = 2;
              res += dp[cur][ns][nc];
              res %= mod;
            }
          } else {
            // S¶èÄð·
            for (int cc = 0; cc < 3; cc++) {
              int ns = s;
              // ¡ñÌêÉ'O'©ÂOÌêÉ'J'
              if (cc == 1 && curw - 1 >= 0 && pc == 0) {
                ns |= (1 << (curw - 1));
                int nc = cc;
                if (curw + 1 == W)
                  nc = 2;
                res += dp[cur][ns][nc];
                res %= mod;
              }
              // ¡ñÌêÉ'I'©ÂãÌrbgª1
              else if (cc == 2 && ((s >> curw) & 1)) {
                res += 0;
              }
              // »êÈOÈçAÊÉÄA
              else {
                // 0ðèÄ
                ns &= ~(1 << (curw - 1));
                int nc = cc;
                if (curw + 1 == W)
                  nc = 2;
                res += dp[cur][ns][nc];
                res %= mod;
              }
            }
          }
        }
        dp[nxt][s][pc] = res % mod;
      }
    }
  }
  long long res = 1;
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      if (field[i][j] == '?') {
        res *= 3;
        res %= mod;
      }
  return (res - dp[0][0][2] + mod) % mod;
}

int main() {

  cin >> H >> W;
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      cin >> field[i][j];
  cout << solve() << endl;

  return 0;
}