2089-Mysterious Dungeons
問題概要
部屋の情報が以下のように与えられる.
@ | 主人公の初期位置 |
ゴール | |
小文字英字(a〜z) | 同じ大文字英字("a"cなら"A"c)がOFFの場合ONにし,ONの場合はOFFにする |
大文字英字(A〜Z) | 初期状態ではONで,ONの場合は通行不能でOFFの場合しか通行可能 |
. | 常に通行可能 |
# | 常に通行できない |
主人公がゴールに辿りつける場合は最短時間を,それ以外の場合は-1を出力せよ.
考え方
英字のONOFFの状態をbitで持ってBFSするだけ
実装(C++)
#include <vector> #include <iostream> #include <queue> #include <bitset> #include <map> using namespace std; int H,W,sx,sy; vector<string> MAP; struct state{ int used; int x,y; }; int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0}; bool operator<(const state &a,const state &b){ return a.x==b.x?(a.y==b.y?a.used<b.used:a.y<b.y):a.x<b.x; } bool operator>(const state &a,const state &b){ return b<a; } int solve(){ queue<state> que; map<state,short> turn; state t; t.x=sx;t.y=sy;t.used=int(); que.push(t); turn.insert(make_pair(t,0)); while(!que.empty()){ t=que.front();que.pop(); map<state,short>::iterator it=turn.find(t); //cout<<t.x<<","<<t.y<<","<<t.used<<endl; int now=(*it).second; for(int i=0;i<4;i++){ int nx=t.x+dx[i],ny=t.y+dy[i]; if(MAP[nx][ny]=='#')continue; if(MAP[nx][ny]=='<')return now+1; if(MAP[nx][ny]>='a'&&MAP[nx][ny]<='z'){ state next; next.x=nx;next.y=ny; next.used=t.used^(1<<(MAP[nx][ny]-'a')); map<state,short>::iterator it2=turn.find(next); if(it2!=turn.end())continue; turn.insert(it2,make_pair(next,now+1)); que.push(next); }else if((MAP[nx][ny]=='.')||(MAP[nx][ny]>='A'&&MAP[nx][ny]<='Z'&&(t.used&(1<<(MAP[nx][ny]-'A')))>0)){ state next; next.x=nx;next.y=ny; next.used=t.used; map<state,short>::iterator it2=turn.find(next); if(it2!=turn.end())continue; turn.insert(it2,make_pair(next,now+1)); que.push(next); } } } return -1; } int main() { for(;cin>>H>>W;){ if(H==0)break; MAP.clear(); for(int i=0;i<W;i++){ string t; cin>>t; MAP.push_back(t); } for(int i=0;i<W;i++)for(int j=0;j<H;j++){ if(MAP[i][j]=='@'){ sx=i;sy=j; MAP[i][j]='.'; break; } } cout<<solve()<<endl; } return 0; }