AOJ : 1059 - Mysterious Onslaught

問題概要

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1059&lang=jp
日本語の問題文なので説明省略です.
みょんみょん

アルゴリズム

bitDPを行いました.
左上の1になっているマスを0にするように, みょんを行います.
これを何回か行えば, 必ず全てのマスが0になることがわかります.
この操作を再帰で書いて, メモ化しました.


マップの状態は, ビットで持つようにしました.
高々25ビットなので, これであらわせます.
みょんの操作もXORを行うだけになるので, 非常に書きやすいです.

類題

  • AOJ 0131
    • 左上からという発想が似ている

プログラム

#define MAX 999999999

int n;                      //マップの大きさ
int xorMemo[5][5][5][5][5]; //みょんの操作用
short dp[5][1<<25];         //メモ化用

int solve(int bit){
  if(bit == 0) return 0;
  if(dp[n-1][bit] != -1) return dp[n-1][bit];

  //1になっている左上の座標を探す
  int li,lj;
  for(li=0;li<n;li++){
    for(lj=0;lj<n;lj++){
      if((bit & (1<<(n*li+lj))) != 0){
        break;
      }
    }
    if(lj != n) break;
  }

  //[li][lj]から右下に伸びる長方形でみょんを行う
  int res = MAX;
  REP(hi,li,n){
    REP(hj,lj,n){
      int next = (bit ^ xorMemo[n-1][li][lj][hi][hj]);
      res = min(res,solve(next)+1);
    }
  }

  return dp[n-1][bit]=res;
}

int main(){
  //みょんをXOR操作で行うためのビットを全て生成
  memset(xorMemo,0,sizeof(xorMemo));
  REP(m,1,6){
    rep(li,m){
      rep(lj,m){
        REP(hi,li,m){
          REP(hj,lj,m){
            REP(i,li,hi+1){
              REP(j,lj,hj+1){
                xorMemo[m-1][li][lj][hi][hj] |= (1<<(i*m+j));
              }
            }
          }
        }
      }
    }
  }

  memset(dp,-1,sizeof(dp));
  while(cin>>n,n){
    int bit = 0;
    rep(i,n){
      rep(j,n){
        int x;
        cin>>x;

        if(x == 1){
          bit |= (1<<(i*n+j));
        }
      }
    }

    int ans = solve(bit);
    rep(i,ans) cout<<"myon";
    cout<<endl;
  }
}