Particle

競技プログラミングについての雑記

AOJ 0559: JOI Flag

解法

bitDP(の別解)で解きました.
下から見ていき、Iになっている場所と、直前がJでその下がIという状態を持つことでも解ける.
JOが隣り合う状態を持つ方が状態数が少なくなるが, この解法でもO(n^2*2^n)なのでAOJでは間に合う.

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
#define N 20
string g[N];
int dp[2][2][1<<N], mod = 100000;

int main(){
	int h, w;
	cin>>h>>w;
	for(int i = 0; i < h; i++) cin>>g[i];
	int res = 0, f = 0;
	dp[0][0][0] = 1;
	for(int i = h-1; i >= 0; i--){
		for(int j = 0; j < w; j++){
			f ^= 1;
			memset(dp[f], 0, sizeof(dp[f]));
			char c = g[i][j];
			if(c=='?') (res*=3)%=mod;
			for(int k = 0; k < 1<<w; k++){
				int k2 = k&~(1<<j);
				int t1 = dp[!f][0][k], t2 = dp[!f][1][k];
				if(c=='?'||c=='I') (dp[f][0][k2|(1<<j)]+=t1+t2)%=mod;
				if(c=='?'||c=='O'){
					(res += t2)%=mod;
					(dp[f][0][k2]+=t1)%=mod;
				}
				if(c=='?'||c=='J') (dp[f][j<w-1&&((k>>j)&1)][k2]+=t1+t2)%mod;
			}
		}
	}
	cout<<res<<endl;
	return 0;