AOJ : 2297 - Rectangular Stamps
問題概要
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2297
日本語の問題文なので, 説明は省略です.
アルゴリズム
マップが4*4なので, 16ビットの2進数の状態にすることができます.
各ビットが, 1のときは目的の色に塗れていることを表し, 0のときは目的の色に塗れていないことを表すように, 状態を管理しましょう.
あとは, 全ての塗り方を試すように, 幅優先で遷移していけば解くことができます.
やらかしたミス
- マップの大きさが t[4][4] になってた. ヌル文字も考えて, [5][5]にしておく必要があった.
- BFSの遷移のとき, 六重ループで書いてたらTLE. 明らかに内側の二重ループは, 前処理しておくべきだった.
プログラム
#define REP(i,a,b) for(int i=a;i<b;i++) #define rep(i,n) REP(i,0,n) typedef pair<int,int> P; int n; int h[16],w[16]; int b[16][3][8][8],b2[16][3][8][8]; bool closed[1<<16]; char t[10][10],ch[]="RGB"; void solve(){ queue<P> open; memset(closed,0,sizeof(closed)); open.push(P(0,0)); closed[0] = true; while(!open.empty()){ P p = open.front(); open.pop(); if(p.second == (1<<16)-1){ printf("%d\n",p.first); return; } //以下, BFSの遷移 rep(k,n){ //どのスタンプを使うか rep(color,3){ //どの色で塗るか REP(si,-h[k]+1,4){ //開始行 REP(sj,-w[k]+1,4){ //開始列 int bit = p.second; bit |= b[k][color][si+4][sj+4]; bit -= (bit & b2[k][color][si+4][sj+4]); if(!closed[bit]){ closed[bit] = true; open.push(P(p.first+1,bit)); } } } } } } } int main(void){ while(scanf("%d",&n) != EOF){ rep(i,n){ scanf("%d%d",&h[i],&w[i]); } rep(i,4){ scanf("%s",t[i]); } //スタンプで色を塗るとき用の前処理 rep(k,n){ rep(color,3){ REP(si,-h[k]+1,4){ REP(sj,-w[k]+1,4){ int bit = 0; int bit2 = 0; REP(i,si,si+h[k]){ REP(j,sj,sj+w[k]){ if(i < 0 || j < 0 || 4 <= i || 4 <= j) continue; int tmpBit = (1<<(i*4+j)); if(t[i][j] == ch[color]){ bit |= tmpBit; } else{ bit2 |= tmpBit; } } } b[k][color][si+4][sj+4] = bit; b2[k][color][si+4][sj+4] = bit2; } } } } solve(); } }