読者です 読者をやめる 読者になる 読者になる

kanetaiの二次記憶装置

プログラミングに関するやってみた、調べた系のものをQitaに移して、それ以外をはてブでやる運用にしようと思います。http://qiita.com/kanetai

迷路の最短路

迷路の最短路(プログラミングコンテストチャレンジブック p37)

大きさN×Mの迷路が与えられる。'#','.','S','G'はそれぞれ、壁、通路、スタート、ゴールを示す。1ターンに4近傍の通路に移動できる。スタートからゴールまで移動するのに必要なターン数を求める。
制約
N.M \leq 100

アルゴリズム

幅優先探索(BFS:Breadth-First Search)を使って、同じ状態には1度しか通らないようにする。一番最初にゴールにたどり着いたときのターン数が最小のターン数になる。
求めるものが、最小ターンなのでLake Counting(PKU No.2386)のようなDFSだと駄目。
DFSのときはスタックを、BFSのときはキューを使うことになる。

コード

import java.util.*;
public class shortest_path_of_labyrinth {
	static Scanner scanner;
	static Pos[] diff;
	char[][] map;
	Queue<Pos> q;
	Pos start,goal;
	public static void main(String[] args) {
		scanner = new Scanner(System.in);
		// 4近傍の方向ベクトル初期化
		diff = new Pos[]{ new Pos(-1,0), new Pos(0,-1), new Pos(1,0), new Pos(0,1) };
		new shortest_path_of_labyrinth();
	}
	shortest_path_of_labyrinth(){
		int N = scanner.nextInt();
		int M = scanner.nextInt();
		map = new char[N+2][M+2];
		//周りを#で埋めて番兵的に使う
		for(int i=0; i < N+2; i++){
			if( i==0 || i==N+1 ) Arrays.fill(map[i], '#');
			else{
				String line = scanner.next();
				line = "#" + line + "#";
				int idx;
				if( (idx=line.indexOf('S')) >= 0 ) start = new Pos(i,idx,0); //スタート地点記録 ※0ターン目に到達可能
				if( (idx=line.indexOf('G')) >= 0 ) goal = new Pos(i,idx); //ゴール地点記録
				map[i] = line.toCharArray();
			}
		}
		System.out.println( solve() );
	}
	
	int solve(){
		q = new LinkedList<Pos>();
		return BFS();
	}
	int BFS(){
		q.offer( start );
		map[goal.y][goal.x] = '.'; //ゴール地点を移動可能なマス'.'に変えている。
		Pos p;
		while( (p = q.poll()) != null ){
			if( p.isEqual_Pos(goal) ) return p.count; //ゴール
			for(int i = 0; i < 4; i++){ //4近傍をキューに追加
				if( map[ p.y + diff[i].y ][ p.x + diff[i].x ] == '.'){
					map[ p.y + diff[i].y ][ p.x + diff[i].x ] = '#'; //移動不可能なマス'#'に変える(同じマスを再度訪問しないようにしている)
					q.offer( new Pos( p.y + diff[i].y, p.x+diff[i].x, p.count+1 ) );
				}
			}
		}
		return -1; //失敗
	}
}

class Pos{
	int x,y,count; //map[y][x]へターン数(count)で到達可能であることを示す。
	Pos(int y, int x){ this.y = y; this.x = x; this.count = -1; }
	Pos(int y, int x, int count){ this.y = y; this.x = x; this.count = count; }
	boolean isEqual_Pos(Pos b){ return (x == b.x && y == b.y); } //xとyだけで比較
}