AOJ 0203 - A New Plan of Aizu Ski Report

memo[y][x]: 座標(y, x)からはじめたときに滑れるパターンの総数
(座標は(0, 0)を始点とする)

w*hのコースでの滑り終わりは(x, h-1)

(1)の!(map[y+1][x+i] == 2 && i != 0)は
A: 元のx座標と次に行くx座標が同じ
B: 次のところにはジャンプ台があるとして,
カルノー図を書くと,

¬AA
¬B1
B11

これは¬(A∧¬B)であることを利用している.

#include<iostream>

int w, h;
int map[16][15], memo[16][15];

int rec(int x, int y){
	if(memo[y][x] >= 0){
		return memo[y][x];
	}

	if(map[y][x] == 1){
		return 0;
	}

	if(y >= h-1){
		return 1;
	}

	int res = 0;
	if(map[y][x] == 0){
		for(int i=-1;i<2;i++){
			if(x+i >= 0 && x+i < w && !(map[y+1][x+i] == 2 && i != 0)){//(1)
				res += rec(x+i, y+1);
			}
		}
		return memo[y][x] = res;
	}else if(map[y][x] == 2){
		return memo[y][x] = rec(x, y+2);
	}
}

int main(){
	while(std::cin >> w >> h, w){

		for(int i=0;i<16;i++){
			for(int j=0;j<15;j++){
				memo[i][j] = -1;
				map[i][j] = 0;
			}
		}

		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				std::cin >> map[i][j];
			}
		}

		int res = 0;
		for(int i=0;i<w;i++){
			res += rec(i, 0);
		}

		std::cout << res << std::endl;
	}
}