Problem:
パスタ (Pasta)

問題

あなたはパスタが大好物であり，毎日，晩御飯にパスタを作って食べている．あなたはトマトソース，クリームソース，バジルソースの 3 種類のパスタを作ることができる．

N 日間の晩御飯の予定を考えることにした．それぞれの日に 3 種類のパスタから 1 種類を選ぶ．ただし，同じパスタが続くと飽きてしまうので，3 日以上連続して同じパスタを選んではいけない．また，N 日のうちの K 日分のパスタはすでに決めてある．

入力として N の値と，K 日分のパスタの情報が与えられたとき，条件をみたす予定が何通りあるかを 10000 で割った余りを求めるプログラムを作成せよ．

入力

入力は K + 1 行からなる．

1 行目には 2 つの整数 N, K (3 ≦ N ≦ 100，1 ≦ K ≦ N) が空白を区切りとして書かれている．

1 + i 行目 (1 ≦ i ≦ K) には 2 つの整数 Ai, Bi (1 ≦ Ai ≦ N，1 ≦ Bi ≦ 3) が空白を区切りとして書かれている．これは，Ai 日目のパスタはすでに決まっており，Bi = 1 のときはトマトソースであり，Bi = 2 のときはクリームソースであり，Bi = 3 のときはバジルソースであることを表す．Ai (1 ≦ i ≦ K) は全て異なる．与えられる入力データにおいて，条件をみたす予定は 1 通り以上あることが保証されている．

出力

条件をみたす予定が何通りあるかを 10000 で割った余りを 1 行で出力せよ．

入出力例

入力例 1

5 3
3 1
1 1
4 2

出力例 1

6

入出力例 1 において，あなたは 5 日間の予定を考える．1 日目と 3 日目はトマトソースであり，4 日目はクリームソースである．また，3 日以上連続して同じパスタを選んではいけない．これらの条件をみたす予定は 6 通りある．

 1日目 

 2日目 

 3日目 

 4日目 

 5日目 

予定 1   

1

2

1

2

1

予定 2   

1

2

1

2

2

予定 3   

1

2

1

2

3

予定 4   

1

3

1

2

1

予定 5   

1

3

1

2

2

予定 6   

1

3

1

2

3

この表では，1 はトマトソースを，2 はクリームソースを，3 はバジルソースを表す．

入力例 2

20 5
10 2
4 3
12 1
13 2
9 1

出力例 2

2640

入出力例 2 において，条件をみたす予定は全部で 4112640 通りある．それを 10000 で割った余りである 2640 を出力する．

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in JAVA (judge verdict: Accepted)

import java.util.Scanner;
public class Main {
	static int all_day;
	static final int set_data = 10000;
	static long[][] tomato = new long[2][]; 
	static long[][] cream = new long[2][];
	static long[][] basilico = new long[2][];
	
	static void setData(int[][] data, int today) {
		boolean flag = false;
		for(int r = 0; r < data.length; r++) {
			if((data[r][0] - 1) == today) {
				//System.out.println("種類：" + data[r][1] + "今日は" + (today + 1) + "日");
				Type_accumulate(data[r][1], today);
				flag = true;
			}
			if(flag == false && r == data.length - 1) {
				//System.out.println("全体処理かかります。");
				Not_Only_accumulate(today);
			}
		}
	}
	
	static void Not_Only_accumulate(int today) {
		//トマト
		tomato[0][today] = tomato[1][today - 1];
		tomato[1][today] = cream[0][today - 1] + cream[1][today - 1] + basilico[0][today - 1] + basilico[1][today - 1] % set_data;
		//クリーム
		cream[0][today] = cream[1][today - 1];
		cream[1][today] = tomato[0][today - 1] + tomato[1][today - 1] + basilico[0][today - 1] + basilico[1][today - 1] % set_data;
		//バジル
		basilico[0][today] = basilico[1][today - 1];
		basilico[1][today] = tomato[0][today - 1] + tomato[1][today - 1] + cream[0][today - 1] + cream[1][today - 1] % set_data;
	}
	
	static void Type_accumulate(int kind, int today) {
		switch(kind) {
		case 1: //トマトの場合
			tomato[0][today] = tomato[1][today - 1];
			tomato[1][today] = cream[0][today - 1] + cream[1][today - 1] + basilico[0][today - 1] + basilico[1][today - 1] % set_data;
			//System.out.println("トマトのみ処理入りました〜");
			break;
		case 2: //クリームの場合
			cream[0][today] = cream[1][today - 1];
			cream[1][today] = tomato[0][today - 1] + tomato[1][today - 1] + basilico[0][today - 1] + basilico[1][today - 1] % set_data;
			//System.out.println("クリームのみ処理入りました〜");
			break;
		case 3: //バジルの場合
			basilico[0][today] = basilico[1][today - 1];
			basilico[1][today] = tomato[0][today - 1] + tomato[1][today - 1] + cream[0][today - 1] + cream[1][today - 1] % set_data;
			//System.out.println("バジルのみ処理入りました〜");
			break;
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner stdIn = new Scanner(System.in);
		
		all_day = stdIn.nextInt();
		for(int r = 0; r < tomato.length; r++) {
			tomato[r] = new long[all_day];
			cream[r] = new long[all_day];
			basilico[r] = new long[all_day];
		}
		int decided_day = stdIn.nextInt();
		int[][] data = new int[decided_day][2];
		int counter = 0;
		
		for(int r = 0; r < decided_day; r++) { //読み込み
			data[r][0] = stdIn.nextInt(); //day
			data[r][1] = stdIn.nextInt(); //kind
			//System.out.println("DEBUG");
			//System.out.println(r); //日にちDEBUG
			if(counter != 1 && data[r][0] == 1) {
				//System.out.println("テストケースでは一度しか出さないメッセージ");
				//System.out.println("DEBUG1");
				//System.out.println("Array \"tomato\" is accept order before this order.");
				switch(data[r][1]) { //恐らくエラー箇所
				case 1: tomato[1][0] = 1; break;
				case 2: cream[1][0] = 1; break;
				default: basilico[1][0] = 1; break;
				}
				counter++;
			} else if(counter != 1 && r == decided_day - 1){
				//System.out.println("テストケースでは一度しか出さないメッセージ");
				//System.out.println("DEBUG2");
				tomato[1][0] = 1;
				cream[1][0] = 1;
				basilico[1][0] = 1;
				counter++;
			}
		}
		
		
		//System.out.println("DEBUG BEFORE SUBROUTINE");
		for(int r = 1; r < all_day; r++) { //r + 1 = 日にち
			setData(data, r);
		}
		/*for(int r = 0; r < 2; r++) {
			System.out.println("tomato:" + tomato[r][all_day - 2]);
			System.out.println("cream:" + cream[r][all_day - 2]);
			System.out.println("basilico:" + basilico[r][all_day - 2]);
		}*/
		/*for(int r = 0; r < 2; r++) { //全データの確認
			for(int c = 0; c < all_day; c++) {
				System.out.println("tomato:" + tomato[r][c]);
				System.out.println("cream:" + cream[r][c]);
				System.out.println("basilico:" + basilico[r][c]);
			}
			System.out.println();
		}*/
		System.out.println((tomato[0][all_day - 1] + tomato[1][all_day - 1] + cream[0][all_day - 1] + cream[1][all_day - 1] + basilico[0][all_day - 1] + basilico[1][all_day - 1]) % set_data);		
	}
}