AOJ : 2132 - Left Hand Rule
問題概要
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2132
迷路の壁情報と, スタート位置・ゴール位置が与えられる.
左手法によりゴールまで辿りつけるならば, 歩数を出力.
辿りつけないならば, Impossibleと出力.
スタート位置は, 一番外側の壁のどこかにあると仮定してよい.
ゴール位置は, マス目のどこかを示している.
アルゴリズム
ひたすら実装です.
迷路のデータ構造は, 「各マスの上下左右に壁があるかないか」を管理する方法で作りました.
迷路を辿るときは, bool used[ 102 (x座標) ][ 102 (y座標) ][ 4 (方向) ] というclosedリスト的なものを作って, 同じ状態に2回以上なったらImpossibleとするようにしました.
プログラム
struct P{ bool wall[4]; }t[200][200]; int w,h,n; int dx[] = {0,1,0,-1}; int dy[] = {-1,0,1,0}; int main(void){ while(scanf("%d%d%d",&w,&h,&n),w||h||n){ /* 壁入力 */ memset(t,0,sizeof(t)); rep(i,h) t[i][0].wall[3] = t[i][w-1].wall[1] = true; rep(j,w) t[0][j].wall[0] = t[h-1][j].wall[2] = true; rep(i,n){ int fx,fy,tx,ty; scanf("%d%d%d%d",&fx,&fy,&tx,&ty); if(fx > tx) swap(fx,tx); if(fy > ty) swap(fy,ty); if(fx == tx){ REP(i,fy,ty){ t[i][fx-1].wall[1] = t[i][fx].wall[3] = true; } } else{ REP(j,fx,tx){ t[fy-1][j].wall[2] = t[fy][j].wall[0] = true; } } } /* スタート位置の情報を, マスとして考えた座標に置き換える */ int x1,y1,x2,y2,gx,gy; scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&gx,&gy); if(x1 > x2) swap(x1,x2); if(y1 > y2) swap(y1,y2); int x=x1,y=y1,d=0; if(x1 == x2){ if(x1 == 0){ d = 1; } else{ d = 3; x--; } } else{ if(y1 == 0){ d = 2; } else{ d = 0; y--; } } /* 迷路辿り */ int res = 1; bool flg = true; //ゴールできたかどうか bool used[102][102][4]; //closedリスト的なやつ memset(used,0,sizeof(used)); while(x != gx || y != gy){ //(x,y)の位置に方向dで来たことがあるならImpossible if(used[x][y][d]){ flg = false; break; } used[x][y][d] = true; //左向いて空いてたらそっちいく if(!t[y][x].wall[(d+1)%4]){ d = (d+1)%4; x += dx[d]; y += dy[d]; res++; } //前向いて空いてたらそっちいく else if(!t[y][x].wall[d]){ x += dx[d]; y += dy[d]; res++; } //右向く else{ d = (d + 3) % 4; } } if(flg){ printf("%d\n",res); } else{ printf("Impossible\n"); } } }