2297-Rectangular Stamps

Rectangular Stamps | Aizu Online Judge

解法

最終状態から見ていく.
色が同じ部分に対して適当にスタンプを押し,その色を?に変える.
というのを繰り返すメモ化.
メモするのは?かどうかという情報のみで良い.

実装(C++)

#include <iostream>
using namespace std;
int N,H[20],W[20];
char MAP[4][4];
#define REP(i,x)for(int i=0;i<(int)x;i++)
int dp[1<<16];
int p2i(int a,int b){
	return a+b*4;
}
int solve(int used){
	int res=99999999;
	if(used==(1<<16)-1)return 0;
	if(dp[used]>=0)return dp[used];
	REP(k,N){
		for(int x=-W[k]+1;x<=3;x++){
			for(int y=-H[k]+1;y<=3;y++){
				bool ok=true;
				int next=used;
				int color=-1;
				for(int tx=x;tx<x+W[k];tx++){
					for(int ty=y;ty<y+H[k];ty++){
						if(tx<0||ty<0||tx>=4||ty>=4)continue;
						if((next>>p2i(tx,ty))&1)continue;
						if(color==-1){
							color=MAP[tx][ty];
						}
						if(MAP[tx][ty]!=color){
							ok=false;
							tx=9999;ty=9999;
							break;
						}else{
							next|=1<<p2i(tx,ty);
						}
					}
				}
				if(ok&&next!=used){
					res=min(res,solve(next)+1);
				}
			}
		}
	}
	return dp[used]=res;

}
int main() {
	cin>>N;
	REP(i,N){
		cin>>H[i]>>W[i];
	}
	for(int i=0;i<4;i++){
		string in;cin>>in;
		for(int j=0;j<4;j++){
			MAP[j][i]=in[j];
		}
	}
	fill(dp,dp+(1<<16),-1);
	cout<<solve(0)<<endl;
	return 0;
}