TopCoder SRM 297 Div1 Medium CageTheMonster
問題
hxwのグリッドで表される迷路がある。
'.'および'^'のマスは何もないマスで、'#'のマスは壁である。
この迷路の'^'のマスのどこかにモンスターを置く。
モンスターは迷路を上下左右の何もないマスに動くことができる。
迷路の外へモンスターが脱出できないように、魔法で壁を置く。
魔法で、一度につき一列または一行を全て壁にすることができる。
モンスターの初期位置が含まれる列または行は選ぶことができない。
魔法の壁は、最小で何回置かなければならないか、求めよ。
制約条件
h,w≦40
方針
モンスターの初期位置を一通り決めたとする。
モンスターより右側に壁を置く場合、その壁はモンスターの一つ右隣の列におくととしてよい。
同様に、4方向に壁を置く場合、その壁はモンスターの隣にあるとしてよい。
これを、全初期位置について、4方向に壁を置くかおかないか全通り試せばいい。
ソースコード
const int dy[]={-1,0,1,0}, dx[]={0,-1,0,1}; bool v[40][40]; bool dfs(int y,int x,int h,int w,vs &maze){ if(y<0||x<0||y>=h||x>=w)return 1; if(v[y][x]||maze[y][x]=='#')return 0; v[y][x]=1; rep(d,4){ int ny=y+dy[d], nx=x+dx[d]; if(dfs(ny,nx,h,w,maze))return 1; } return 0; } class CageTheMonster { public: int capture(vector <string> labyrinth) { vs maze=labyrinth; int h=maze.size(), w=maze[0].size(); int ans=inf; rep(i,h)rep(j,w)if(labyrinth[i][j]=='^'){ rep(mask,1<<4){ maze=labyrinth; if((mask&1)&&j)rep(k,h)maze[k][j-1]='#'; if((mask&2)&&j<w-1)rep(k,h)maze[k][j+1]='#'; if((mask&4)&&i)rep(k,w)maze[i-1][k]='#'; if((mask&8)&&i<h-1)rep(k,w)maze[i+1][k]='#'; memset(v,0,sizeof(v)); if(!dfs(i,j,h,w,maze))ans=min(ans,__builtin_popcount(mask)); } } return ans==inf?-1:ans; } };