AOJ 0568 - Pasta

問題 : http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0568

解法: DP

dp[i][j][k]:=i日目にj-1番目のパスタをk日連続で使ったとした時の通りの数。
ただし(1\le i\le n,1\le j\le 3,1\le k\le2)

漸化式は
dp[i][j][1]=dp[i-1][a][1]+dp[i-1][a][2]+dp[i-1][b][1]+dp[i-1][b][2] ただし(a,b\neq j)
dp[i][j][2]=dp[i-1][j][1] \cdots

と出来る。

※ (2日連続で使うのは前日に(1日だけ)同じパスタを選んでいた場合のみであるから)

あとは条件に従いパスタが決まっている日はそのパスタだけを使うようにすれば良い。

#include<iostream>
#include<map>

#define MOD 10000

using namespace std;

map<int,int>data;

int dp[200][3][3]={0};

int main(){
	int n,k;
	cin>>n>>k;
	for(int i=0;i<k;i++){
		int a,b;
		cin>>a>>b;
		data[a]=b;
	}
	
	for(int i=1;i<=n;i++){
		map<int,int>::iterator pa;
		bool it=false;
		if(data.find(i)!=data.end()){
			pa=data.find(i);
			it=true;
		}
		
		if(i==1){
			if(it){
				dp[i][pa->second-1][1]=1;
			}
			else {
				for(int j=0;j<3;j++){
					dp[i][j][1]=1;
				}
			}
		}
		else {
			if(it){
				for(int j=0;j<3;j++){
					if(j!=pa->second-1)dp[i][pa->second-1][1]+=dp[i-1][j][1]+dp[i-1][j][2];
					dp[i][pa->second-1][1]%=MOD;
				}
				dp[i][pa->second-1][2]=dp[i-1][pa->second-1][1];
			}
		
			else {
				for(int k=0;k<3;k++){
					for(int j=0;j<3;j++){
						if(j!=k)dp[i][k][1]+=dp[i-1][j][1]+dp[i-1][j][2];
						dp[i][k][1]%=MOD;
					}
					dp[i][k][2]=dp[i-1][k][1];
				}
				
			}
		}
		
	}
	
	int ans=0;
	for(int i=0;i<3;i++){
		ans+=dp[n][i][1]+dp[n][i][2];
	}
	cout<<ans%MOD<<endl;
}