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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;

#define mod 100000
#define INF 2000000000
#define LLINF 4000000000000000000
#define SIZE 50010

// [M???][N???][??????=OI,J=0,1][???20???JO???][???,???]
// 20*20*3*(2^20)
int dp[2][2][1 << 19] = {0};

void dp_init(int k) {

  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < (1 << 19); j++) {
      dp[k][i][j] = 0;
    }
  }
}

int main() {
  int M, N, ans = 0, ans2;
  int af_j, af_i;
  char in[20][21];
  int mm[20][20];

  scanf("%d%d", &M, &N);

  for (int i = 0; i < M; i++) {
    scanf("%s", in[i]);
  }

  for (int i = 0; i < M; i++) {
    for (int j = 0; j < N; j++) {
      if (in[i][j] == '?')
        mm[i][j] = -1;
      if (in[i][j] == 'J')
        mm[i][j] = 0;
      if (in[i][j] == 'O')
        mm[i][j] = 1;
      if (in[i][j] == 'I')
        mm[i][j] = 2;
    }
  }
  for (int i = 0; i < 3; i++) {
    if (mm[0][0] >= 0)
      if (i != mm[0][0])
        continue;

    dp[0][(i == 0)][0] += 1;
  }

  for (int m = 0; m < M; m++) {
    for (int n = 0; n < N; n++) {
      ans2 = 0;
      if (m + n == 0)
        continue;

      dp_init((m * N + n) % 2);

      for (int i = 0; i < 2; i++) {
        for (int j = 0; j < (1 << (N - 1)); j++) {

          for (int k = 0; k < 3; k++) {

            if (mm[m][n] >= 0)
              if (k != mm[m][n])
                continue;

            af_j = (j % (1 << (N - 2))) * 2;

            af_i = (k == 0);

            if (i == 1 && k == 1)
              af_j += 1; // JO

            if ((j >> (N - 2)) == 1 && k == 2 && n < N - 1) {
              ans2 += dp[(m * N + n + 1) % 2][i][j];
            } else {
              dp[(m * N + n) % 2][af_i][af_j] += dp[(m * N + n + 1) % 2][i][j];
            }

            dp[(m * N + n) % 2][af_i][af_j] %= mod;
            ans2 %= mod;
          }
        }
      }

      if (mm[m][n] >= 0)
        ans2 += ans;
      else
        ans2 += ans * 3;

      ans = ans2 % mod;
    }
  }

  printf("%d\\n", ans);

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;

#define mod 100000
#define INF 2000000000
#define LLINF 4000000000000000000
#define SIZE 50010

// [M???][N???][??????=OI,J=0,1][???20???JO???][???,???]
// 20*20*3*(2^20)
int dp[2][2][1 << 19][2] = {0};

void dp_init(int k) {

  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < (1 << 19); j++) {
      dp[k][i][j][0] = dp[k][i][j][1] = 0;
    }
  }
}

int main() {
  int M, N, ans = 0;
  int af_j, af_i;
  char in[20][21];
  int mm[20][20];

  scanf("%d%d", &M, &N);

  for (int i = 0; i < M; i++) {
    scanf("%s", in[i]);
  }

  for (int i = 0; i < M; i++) {
    for (int j = 0; j < N; j++) {
      if (in[i][j] == '?')
        mm[i][j] = -1;
      if (in[i][j] == 'J')
        mm[i][j] = 0;
      if (in[i][j] == 'O')
        mm[i][j] = 1;
      if (in[i][j] == 'I')
        mm[i][j] = 2;
    }
  }
  for (int i = 0; i < 3; i++) {
    if (mm[0][0] >= 0)
      if (i != mm[0][0])
        continue;

    dp[0][(i == 0)][0][0] += 1;
  }

  for (int m = 0; m < M; m++) {
    for (int n = 0; n < N; n++) {
      if (m + n == 0)
        continue;

      dp_init((m * N + n) % 2);

      for (int i = 0; i < 2; i++) {
        for (int j = 0; j < (1 << (N - 1)); j++) {

          for (int k = 0; k < 3; k++) {

            if (mm[m][n] >= 0)
              if (k != mm[m][n])
                continue;

            af_j = (j % (1 << (N - 2))) * 2;

            af_i = (k == 0);

            if (i == 1 && k == 1)
              af_j += 1; // JO

            dp[(m * N + n) % 2][af_i][af_j][1] +=
                dp[(m * N + n + 1) % 2][i][j][1];

            if ((j >> (N - 2)) == 1 && k == 2 && n < N - 1) {
              dp[(m * N + n) % 2][af_i][af_j][1] +=
                  dp[(m * N + n + 1) % 2][i][j][0];
            } else {
              dp[(m * N + n) % 2][af_i][af_j][0] +=
                  dp[(m * N + n + 1) % 2][i][j][0];
            }

            dp[(m * N + n) % 2][af_i][af_j][0] %= mod;
            dp[(m * N + n) % 2][af_i][af_j][1] %= mod;
          }
        }
      }
    }
  }

  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < (1 << (N - 1)); j++) {
      ans += dp[(M * N - 1) % 2][i][j][1];

      ans %= mod;
    }
  }

  printf("%d\\n", ans);

  return 0;
}