Language: C++

# include <iostream>
# include <algorithm>
# include <vector>
# include <string>
# include <set>
# include <map>
# include <cmath>
# include <iomanip>
# include <functional>
# include <utility>
# include <stack>
# include <queue>
# include <list>
# include <tuple>
# include <unordered_map>
# include <numeric>
# include <complex>
# include <bitset>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
typedef pair<LL, LL> P;
constexpr int INF = 2000000000;
constexpr int HINF = INF / 2;
constexpr double DINF = 100000000000000000.0;
constexpr long long LINF = 9223372036854775807;
constexpr long long HLINF = 4500000000000000000;
constexpr long long MMOD = 500000004;
const double PI = acos(-1);
int dx[4] = { 0,1,0,-1 }, dy[4] = { 1,0,-1,0 };
# define ALL(x)      (x).begin(),(x).end()
# define UNIQ(c)     (c).erase(unique(ALL((c))), end((c)))
# define mp          make_pair
# define eb          emplace_back
# define FOR(i,a,b)  for(int i=(a);i<(b);i++)
# define RFOR(i,a,b) for(int i=(a);i>=(b);i--)
# define REP(i,n)    FOR(i,0,n)
# define INIT        std::ios::sync_with_stdio(false);std::cin.tie(0)

constexpr int MAX_N = 20;
constexpr int MAX_M = 20;
constexpr int MOD = 100000;
constexpr char JOI[] = "JOI";

int n, m;
char field[MAX_M][MAX_N];
int dp[2][1 << MAX_N][2];//dp[current or next][直前N文字（前の一列）に"JO"があるか][直前の文字が"J"なのかどうか]

int main() {
	std::cin.tie(0);
	std::ios::sync_with_stdio(false);

	std::cin >> m >> n;

	for (int i = 0; i < m; ++i) {
		for (int j = 0; j < n; ++j) {
			std::cin >> field[i][j];
		}
	}

	dp[0][0][0] = 1;

	int crt = 0, nxt = 1;

	for (int i = 0; i < m; ++i) {
		for (int j = 0; j < n; ++j) {
			memset(dp[nxt], 0, sizeof(dp[nxt]));

			for (int bit = 0; bit < (1 << n); ++bit) {
				for (int f = 0; f < 2; ++f) {//直前の文字が'J'なのかどうか
					if (dp[crt][bit][f] > 0) {//そもそも、存在しない場合は処理しない
						for (int k = 0; k < 3; ++k) {//文字を三通り当てはめる、但し'?'の時は三通り全て当てはめる
							if (field[i][j] != '?' && field[i][j] != JOI[k]) {
								continue;
							}//文字が今回調べるべきでないとき
							if (bit >> j & 1 && JOI[k] == 'I') {
								continue;
							}//「良い旗」ができてしまったとき

							int nbit = bit & ~(1 << j);//現在の位置のJOのbitを消去する
							int nf = JOI[k] == 'J';//次のfを求める

							if (JOI[k] == 'O' && f == 1) {
								nbit |= 1 << (j - 1);
							}//JOができた時は次のビットにそれを適応する

							dp[nxt][nbit][nf] += dp[crt][bit][f];
							if (dp[nxt][nbit][nf] > MOD) {
								dp[nxt][nbit][nf] -= MOD;
							}
						}
					}
				}
			}

			std::swap(crt, nxt);
		}
		for (int bit = 0; bit < (1 << n); ++bit) {
			dp[crt][bit][0] += dp[crt][bit][1];
			if (dp[crt][bit][0] >= MOD) {
				dp[crt][bit][0] -= MOD;
			}

			dp[crt][bit][1] = 0;
		}//行が変わるとき、前のますが'J'であることはなくなるので、それを処理する。
	}
	int ans = 1;//余事象
	for (int i = 0; i < m; ++i) {
		for (int j = 0; j < n; ++j) {
			if (field[i][j] == '?') {
				ans = (ans * 3) % MOD;
			}
		}
	}

	for (int bit = 0; bit < 1 << n; ++bit) {
		ans = (ans + MOD - dp[crt][bit][0]) % MOD;
	}

	std::cout << ans << std::endl;
}


Compiler output:
a.cc: In function 'int main()':
a.cc:67:25: error: 'memset' was not declared in this scope
   67 |                         memset(dp[nxt], 0, sizeof(dp[nxt]));
      |                         ^~~~~~
a.cc:19:1: note: 'memset' is defined in header '<cstring>'; this is probably fixable by adding '#include <cstring>'
   18 | # include <bitset>
  +++ |+#include <cstring>
   19 | using namespace std;