1243-Weather Forecast

問題概要

4x4のマスがあり,日ごとに雨が降ってはいけないマスが与えられる.
2x2の雲を神様が動かすとき,雨が降ってはいけないマスには雨を降らさず,かつ,すべてのマスのうち7日間連続で雨が降らないことはないという条件を見たす,雲の動かしかたはあるか.

解法

メモ化DFS
雲の移動を全部試してみる.
"7日間連続で雨が降らないことはない"というのは4隅を調べるだけで十分.

実装(C++)

#include <cstdio>
#include <cstring>
using namespace std;
int n;
int data[365][4][4];
char ac[365][3][3][7][7][7][7];
int dx[4]={1,0,-1,0},q[4]={1,1,1,1};
int dfs(int d,int x,int y,int v[4]){
	int k[4]={v[0],v[1],v[2],v[3]};
	if(n==d)return 1;
	if(x==0&&y==0)k[0]=0;
	if(x==2&&y==0)k[1]=0;
	if(x==0&&y==2)k[2]=0;
	if(x==2&&y==2)k[3]=0;
	for(int i=0;i<4;i++){
		if(k[i]==7)return 0;
	}

	for(int xx=0;xx<4;xx++)for(int yy=0;yy<4;yy++){
		if(data[d][xx][yy]==1&&x<=xx&&xx<=x+1&&y<=yy&&yy<=y+1){
			return 0;
		}
	}
	if(ac[d][x][y][k[0]][k[1]][k[2]][k[3]])return 0;
	ac[d][x][y][k[0]][k[1]][k[2]][k[3]]=1;
	int next[4]={k[0]+1,k[1]+1,k[2]+1,k[3]+1};
	//雲を動かしてみる
	for(int j=0;j<3;j++){
		for(int i=0;i<4;i++){
			int nx=x+dx[i]*j,ny=y+dx[i^1]*j;
			if(nx>=0&&nx<3&&ny>=0&&ny<3){
				if(dfs(d+1,nx,ny,next))return 1;
			}
		}
	}
	return 0;
}
int main() {
	while(scanf("%d",&n),n){
		for(int i=0;i<n;i++){
			for(int x=0;x<4;x++){
				for(int y=0;y<4;y++){
					scanf("%d",&data[i][x][y]);
				}
			}
		}
		memset(ac,0,3*3*7*7*7*7*n);
		printf("%d\n",dfs(0,1,1,q));
	}
	return 0;
}