AOJ2132 Left Hand Rule

問題リンク Left Hand Rule

  • 概要

W*Hの長方形の壁の状態が与えられる。長方形の周囲には1か所だけ長さ1の穴が空いているが他の箇所は全て壁になっている。この穴が入口となる。入口から入って左手伝いに進んで行ったとき、目標のマス目に到達するのは何ステップ後かを答えよ。辿りつかない場合はImpossibleとせよ。入口から入るときと、マス目を移動する際に1ステップかかるものとする。
0 < W, H <= 100

  • 解法

シミュレーションです。(x, y, 向いている方向)の状態を遷移させていきます。
壁の情報を扱いやすいように
boolean wall[x][y][dir];
という配列を作っています。(x, y)のマスの方向dirに壁はあるか否かを表します。
これを使うと、状態(x, y, dir)の次の遷移先は、dirを左90度回転させた角度から時計回りに見ていき壁が無い方向Dを見つけたらそちらへ動きます。
wall配列を作るところや、座標管理に気をつけましょう。

  • ソース
import java.util.Scanner;

//Left Hand Rule
public class AOJ2132 {

	void run(){
		Scanner sc = new Scanner(System.in);
		int INF = 1<<29;
		int[][] d = {{0,1},{1,0},{0,-1},{-1,0}};
		for(;;){
			int w = sc.nextInt(), h = sc.nextInt(), n = sc.nextInt();
			if((w|h|n)==0)break;
			boolean[][][] wall = new boolean[w][h][4];
			for(int x=0;x<w;x++)wall[x][0][2] = wall[x][h-1][0] = true;
			for(int y=0;y<h;y++)wall[0][y][3] = wall[w-1][y][1] = true;
			while(n--!=0){
				int x1 = sc.nextInt(), y1 = sc.nextInt(), x2 = sc.nextInt(), y2 = sc.nextInt();
				if(x1==x2){
					for(int y=Math.min(y1, y2);y<Math.max(y1, y2);y++)wall[x1][y][3] = wall[x1-1][y][1] = true;
				}
				else{
					for(int x=Math.min(x1, x2);x<Math.max(x1, x2);x++)wall[x][y1][2] = wall[x][y1-1][0] = true;
				}
			}
			boolean[][][] u = new boolean[w][h][4];
			int px = 0, py = 0, pk = 0, step = 1, res = INF;
			int x1 = sc.nextInt(), y1 = sc.nextInt(), x2 = sc.nextInt(), y2 = sc.nextInt(), gx = sc.nextInt(), gy = sc.nextInt();
			if(x2<x1||(x1==x2&&y2<y1)){
				int tx = x1, ty = y1;
				x1 = x2; y1 = y2; x2 = tx; y2 = ty;
			}
			if(x1==x2){
				if(x1==0){
					wall[x1][y1][3] = false;
					u[x1][y1][1] = true;
					px = x1; py = y1; pk = 1;
				}
				else{
					wall[x1-1][y1][1] = false;
					u[x1-1][y1][3] = true;
					px = x1-1; py = y1; pk = 3;
				}
			}
			else{
				if(y1==0){
					wall[x1][y1][2] = false;
					u[x1][y1][0] = true;
					px = x1; py = y1; pk = 0;
				}
				else{
					wall[x1][y1-1][0] = false;
					u[x1][y1-1][2] = true;
					px = x1; py = y1-1; pk = 2;
				}
			}
			for(boolean f=true;f;step++){
				if(px==gx&&py==gy){
					res = step; break;
				}
				for(int k=3;k<7;k++){
					int nk = (pk+k)%4;
					if(!wall[px][py][nk]){
						px+=d[nk][0]; py+=d[nk][1]; pk=nk;
						if(0<=px&&px<w&&0<=py&&py<h&&!u[px][py][pk]){
							u[px][py][pk] = true;
						}
						else{
							f = false; break;
						}
						break;
					}
				}
			}
			System.out.println(res==INF?"Impossible":res);
		}
	}
	
	public static void main(String[] args) {
		new AOJ2132().run();
	}
}