PKU 1166 The Clocks

http://poj.org/problem?id=1166
9個の時計の針を指定した数字コマンドで指定した位置を90度回転させることができる。
与えられた時計の状態に対して、全ての針が12時を指すようにするための最短コマンドで、かつ辞書順最小なものを出力せよというような問題。

最短路探索+経路復元。
最初、場合分けがものすごく面倒くさいんじゃないかと思いましたが、そうでもありませんね。
時間はあまり余裕ではありませんでした。

bool vis[1<<18];
PI best[1<<18];

string rot[]={"ABDE",
              "ABC",
              "BCEF",
              "ADG",
              "BDEFH",
              "CFI",
              "DEGH",
              "GHI",
              "EFHI",
};

int up1(int st,int p){
  int pst=(st>>p*2)&3;
  pst=(pst+1)&3;
  st&=~(3<<p*2);
  return st|pst<<p*2;
}

main(){
  int st=0;
  rep(i,9){
    int t;
    cin>>t;
    st|=t<<i*2;
  }

  queue<pair<PI,int> >q;
  q.push(mp(mp(st,0),0));
  while(!q.empty()){
    int cst=q.front().F.F,be=q.front().F.S,op=q.front().S;
    q.pop();
    if(vis[cst])continue;
    vis[cst]=true;
    best[cst]=mp(be,op);
    if(cst==0)break;    
    rep(i,9){
      int nst=cst;
      rep(j,SZ(rot[i])){
        nst=up1(nst,rot[i][j]-'A');
      }
      if(vis[nst])continue;
      q.push(mp(mp(nst,cst),i));
    }
  }
  
  vector<int> ans;
  int go=0;
  while(true){
    PI tt=best[go];
    go=tt.F;
    ans.pb(tt.S);
    if(st==go)break;
  }
  reverse(ALL(ans));
  rep(i,SZ(ans)){
    if(i)cout<<' ';
    cout<<ans[i]+1;
  }
  cout<<endl;
}