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

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#define ALL(c) c.begin(), c.end()
#define RALL(c) c.rbegin(), c.rend()
#define SORT(x) sort((x).begin(), (x).end())
#define REP(i, x, y) for (int i = (x); i < (y); ++i)
#define MP(a, b) make_pair((a), (b))
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define dump(x)
#endif

typedef long long int ll;
typedef pair<int, int> pii;
// template<typename T> using vec=std::vector<T>;

const int INF = 1 << 30;
const long long int INF_ = 1LL << 58;
const double EPS = 1e-9;
const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}

void Solve() {
  const int mod = 100000;
  int M, N, ans = 1;
  vector<string> field;
  vector<int> crt, next;
  cin >> M >> N;
  crt.resize(1 << (N + 1));
  next.resize(1 << (N + 1));
  REP(i, 0, M) {
    string str;
    cin >> str;
    field.push_back(str);
  }
  crt[0] = 1;
  REP(y, 0, M) REP(x, 0, N) {
    if (field[y][x] == '?') {
      ans *= 3;
      ans %= mod;
    }
    REP(mask, 0, 1 << (N + 1)) {
      // maskの後ろのほうのbitが新しい.一番最初のbitは直前にJを置いたかどうかのフラグ
      const unsigned int nmask = (mask >> 2) << 1;
      switch (field[y][x]) {
      case '?':
        // J
        if (x + 1 < N) {                // 右端でないならば
          next[nmask | 1] += crt[mask]; // Jを置いたのでフラグが立っている
          next[nmask | 1] %= mod;
        } else { // 右端ならJを置いてもその後に影響しない
          next[nmask] += crt[mask];
          next[nmask] %= mod;
        }
        // O
        if (mask & 1) { // もし直前にJをおいていたら
          next[nmask | (1 << N)] +=
              crt[mask]; // JOの並びができているので最新のbitが立っている
          next[nmask | (1 << N)] %= mod;
        } else {
          next[nmask] +=
              crt[mask]; // 直前にJを置いていないので最新のbitは立っていない
          next[nmask] %= mod;
        }
        // I
        if (((mask >> 2) & 1) !=
            1) { // いま見ているマスの上でJOの並びができていなかったらIが置ける
          next[nmask] += crt[mask];
          next[nmask] %= mod;
        }
        break;
      case 'J':
        if (x + 1 < N) {                // 右端でないならば
          next[nmask | 1] += crt[mask]; // Jを置いたのでフラグが立っている
          next[nmask | 1] %= mod;
        } else { // 右端ならJを置いてもその後に影響しない
          next[nmask] += crt[mask];
          next[nmask] %= mod;
        }
        break;
      case 'O':
        if (mask & 1) { // もし直前にJを置いていたら
          next[nmask | (1 << N)] +=
              crt[mask]; // JOが並びができているので最新のbitが立つ
          next[nmask | (1 << N)] %= mod;
        } else {
          next[nmask] += crt[mask];
          next[nmask] %= mod;
        }
        break;
      case 'I':
        if (((mask >> 2) & 1) !=
            1) { // いま見ているマスの上でJOの並びができていなかったらIが置ける
          next[nmask] += crt[mask];
          next[nmask] %= mod;
        }
        break;
      default:
        break;
      }
    }
    swap(next, crt);
    fill(begin(next), end(next), 0);
  }
  const int invalid = accumulate(begin(crt), end(crt), 0,
                                 [](int a, int b) { return (a + b) % mod; });
  ans = (ans - invalid + mod) % mod;
  cout << ans << endl;
}

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

Error: MLE

Fixed submission:

/*
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

using namespace std;

#define ALL(c) c.begin(),c.end()
#define RALL(c) c.rbegin(),c.rend()
#define SORT(x) sort((x).begin(),(x).end())
#define REP(i,x,y) for(int i=(x);i<(y);++i)
#define MP(a,b) make_pair((a),(b))
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define dump(x)
#endif

typedef long long int ll;
typedef pair<int,int> pii;
//template<typename T> using vec=std::vector<T>;

const int INF=1<<30;
const long long int INF_=1LL<<58;
const double EPS=1e-9;
const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec){
        os << "[";
        for (const auto &v : vec) {
                os << v << ",";
        }
        os << "]";
        return os;
}

const int mod=100000;
int M,N,cnt;
unordered_map<string,int> memo[20][20];
char ch[20][20];

ll Pow(ll a,int b){
        ll res=1;
        while(b>0){
                if(b&1) res*=a;
                a=a*a%mod;
                b>>=1;
        }
        return res%mod;
}

bool Check(int y,int x){
        if(!(y>0&&x>0)) return false;
        char j=ch[y-1][x-1],o=ch[y-1][x],i=ch[y][x-1];
        if(j=='J'&&o=='O'&&i=='I') return true;
        else return false;
}

ll DFS(int y,int x,int done,string state){
        if(y==M) return 0;
        if(x==N) return DFS(y+1,0,done,state);

        dump(y);
        dump(x);
        dump(state);
        REP(i,0,M){
                REP(j,0,N) cout << ch[i][j] << ' ';
                cout << endl;
        }
        cout << endl;

        if(memo[y][x].count(state)==1) return memo[y][x][state];
        if(Check(y,x)) return memo[y][x][state]=Pow(3,cnt-done)%mod;
        ll tmp=0;
        string sub=state.substr(1);
        sub[sub.size()-1]='A';
        if(ch[y][x]=='?'){
                ch[y][x]='J';
                if(y+1<M&&x+1<N) tmp=(tmp+DFS(y,x+1,done+1,sub+'J'))%mod;
                else tmp=(tmp+DFS(y,x+1,done+1,sub+'A'))%mod;
                ch[y][x]='O';
                if(y+1<M&&x>0&&ch[y][x-1]=='J'){
                        sub[sub.size()-1]='J';
                        tmp=(tmp+DFS(y,x+1,done+1,sub+'O'))%mod;
                        sub[sub.size()-1]='A';
                }else tmp=(tmp+DFS(y,x+1,done+1,sub+'A'))%mod;
                ch[y][x]='I';
                if((y>0&&x+1<N&&ch[y-1][x]=='J'&&ch[y-1][x+1]=='O'&&ch[y][x]=='I'))
tmp=(tmp+DFS(y,x+1,done+1,sub+'I'))%mod; else
tmp=(tmp+DFS(y,x+1,done+1,sub+'A'))%mod; ch[y][x]='?'; }else{
                if((y+1<M&&x>0&&ch[y][x-1]=='J'&&ch[y][x]=='O')){
                        sub[sub.size()-1]='J';
                        tmp=(tmp+DFS(y,x+1,done,sub+ch[y][x]))%mod;
                        sub[sub.size()-1]='A';
                }else
if((y+1<M&&x+1<N&&ch[y][x]=='J')||(y>0&&x+1<N&&ch[y-1][x]=='J'&&ch[y-1][x+1]=='O'&&ch[y][x]=='I'))
tmp=(tmp+DFS(y,x+1,done,sub+ch[y][x]))%mod; else
tmp=(tmp+DFS(y,x+1,done,sub+'A'))%mod;
        }
        return memo[y][x][state]=tmp;
}

void Solve(){
        cin >> M >> N;
        REP(i,0,M) REP(j,0,N){
                cin >> ch[i][j];
                if(ch[i][j]=='?') ++cnt;
        }
        cout << DFS(0,0,0,string(N+1,'A')) << endl;
}

int main(){
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        Solve();
        return 0;
}
*/

/*
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#define ALL(c) c.begin(),c.end()
#define RALL(c) c.rbegin(),c.rend()
#define SORT(x) sort((x).begin(),(x).end())
#define REP(i,x,y) for(int i=(x);i<(y);++i)
#define MP(a,b) make_pair((a),(b))
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define dump(x)
#endif

typedef long long int ll;
typedef pair<int,int> pii;
//template<typename T> using vec=std::vector<T>;

const int INF=1<<30;
const long long int INF_=1LL<<58;
const double EPS=1e-9;
const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec){
        os << "[";
        for (const auto &v : vec) {
                os << v << ",";
        }
        os << "]";
        return os;
}

const int mod=100000;
int M,N,cnt;
map<string,int> memo[20][20];
char ch[20][20];

ll Pow(ll a,int b){
        ll res=1;
        while(b>0){
                if(b&1) res*=a;
                a=a*a%mod;
                b>>=1;
        }
        return res%mod;
}

bool Check(int y,int x,string state){
        if(!(y>0&&x>0)) return false;
        char j=state[0],o=state[1],i=state[2];
        if(j=='J'&&o=='O'&&i=='I') return true;
        else return false;
}

ll DFS(int y,int x,int done){
        if(y==M) return 0;
        if(x==N) return DFS(y+1,0,done);
        string state="AAA";
        if(y>0&&x>0) state[0]=ch[y-1][x-1];
        if(y>0) state[1]=ch[y-1][x];
        if(x>0) state[2]=ch[y][x-1];
        dump(y);
        dump(x);
        dump(done);
        dump(state);
        REP(i,0,M){
                REP(j,0,N) cout << ch[i][j] << ' ';
                cout << endl;
        }
        if(memo[y][x].count(state)==1) return memo[y][x][state];
        if(Check(y,x,state)) return memo[y][x][state]=Pow(3,cnt-done)%mod;
        ll tmp=0;
        if(ch[y][x]=='?'){
                ch[y][x]='J';
                tmp=(tmp+DFS(y,x+1,done+1))%mod;
                ch[y][x]='O';
                tmp=(tmp+DFS(y,x+1,done+1))%mod;
                ch[y][x]='I';
                tmp=(tmp+DFS(y,x+1,done+1))%mod;
                ch[y][x]='?';
        }else tmp=(tmp+DFS(y,x+1,done))%mod;
        return memo[y][x][state]=tmp;
}

void Solve(){
        cin >> M >> N;
        REP(i,0,M) REP(j,0,N){
                cin >> ch[i][j];
                if(ch[i][j]=='?') ++cnt;
        }
        cout << DFS(0,0,0) << endl;
        REP(y,0,M){
                REP(x,0,N){
                        dump(y);
                        dump(x);
                        for(auto it=memo[y][x].begin(); it!=memo[y][x].end();
++it){ dump(it->first); dump(it->second);
                        }
                }
        }
}

int main(){
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        Solve();
        return 0;
}
*/

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

using namespace std;

#define ALL(c) c.begin(), c.end()
#define RALL(c) c.rbegin(), c.rend()
#define SORT(x) sort((x).begin(), (x).end())
#define REP(i, x, y) for (int i = (x); i < (y); ++i)
#define MP(a, b) make_pair((a), (b))
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define dump(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define dump(x)
#endif

typedef long long int ll;
typedef pair<int, int> pii;
// template<typename T> using vec=std::vector<T>;

const int INF = 1 << 30;
const long long int INF_ = 1LL << 58;
const double EPS = 1e-9;
const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}

const int mod = 100000;
int M, N, cnt;
unordered_map<string, int> memo[20][20];
char ch[20][20];

ll Pow(ll a, int b) {
  ll res = 1;
  while (b > 0) {
    if (b & 1)
      res *= a;
    a = a * a % mod;
    b >>= 1;
  }
  return res % mod;
}

bool Check(int y, int x) {
  if (!(y > 0 && x > 0))
    return false;
  char j = ch[y - 1][x - 1], o = ch[y - 1][x], i = ch[y][x - 1];
  if (j == 'J' && o == 'O' && i == 'I')
    return true;
  else
    return false;
}

ll DFS(int y, int x, int done, string state) {
  if (y == M)
    return 0;
  if (x == N)
    return DFS(y + 1, 0, done, state);
  /*
  dump(y);
  dump(x);
  dump(state);
  REP(i,0,M){
          REP(j,0,N) cout << ch[i][j] << ' ';
          cout << endl;
  }
  cout << endl;
  */
  if (memo[y][x].count(state) == 1)
    return memo[y][x][state];
  if (Check(y, x))
    return memo[y][x][state] = Pow(3, cnt - done) % mod;
  ll tmp = 0;
  string sub = state.substr(1);
  if (sub[sub.size() - 1] != 'O')
    sub[sub.size() - 1] = 'A';
  if (ch[y][x] == '?') {
    ch[y][x] = 'J';
    if (y + 1 < M && x + 1 < N)
      tmp = (tmp + DFS(y, x + 1, done + 1, sub + 'J')) % mod;
    else
      tmp = (tmp + DFS(y, x + 1, done + 1, sub + 'A')) % mod;
    ch[y][x] = 'O';
    if (y + 1 < M && x > 0 && ch[y][x - 1] == 'J') {
      sub[sub.size() - 1] = 'J';
      tmp = (tmp + DFS(y, x + 1, done + 1, sub + 'O')) % mod;
      sub[sub.size() - 1] = 'A';
    } else
      tmp = (tmp + DFS(y, x + 1, done + 1, sub + 'A')) % mod;
    ch[y][x] = 'I';
    if ((y > 0 && x + 1 < N && ch[y - 1][x] == 'J' && ch[y - 1][x + 1] == 'O' &&
         ch[y][x] == 'I'))
      tmp = (tmp + DFS(y, x + 1, done + 1, sub + 'I')) % mod;
    else
      tmp = (tmp + DFS(y, x + 1, done + 1, sub + 'A')) % mod;
    ch[y][x] = '?';
  } else {
    if ((y + 1 < M && x > 0 && ch[y][x - 1] == 'J' && ch[y][x] == 'O')) {
      sub[sub.size() - 1] = 'J';
      tmp = (tmp + DFS(y, x + 1, done, sub + ch[y][x])) % mod;
      sub[sub.size() - 1] = 'A';
    } else if ((y + 1 < M && x + 1 < N && ch[y][x] == 'J') ||
               (y > 0 && x + 1 < N && ch[y - 1][x] == 'J' &&
                ch[y - 1][x + 1] == 'O' && ch[y][x] == 'I'))
      tmp = (tmp + DFS(y, x + 1, done, sub + ch[y][x])) % mod;
    else
      tmp = (tmp + DFS(y, x + 1, done, sub + 'A')) % mod;
  }
  return memo[y][x][state] = tmp;
}

void Solve() {
  cin >> M >> N;
  REP(i, 0, M) REP(j, 0, N) {
    cin >> ch[i][j];
    if (ch[i][j] == '?')
      ++cnt;
  }
  cout << DFS(0, 0, 0, string(N + 1, 'A')) << endl;
}

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