bfs

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**
 * 
 * @author ramanu_jan
 *
 */

/**
 * 四维点
 */
class Point{
	int x, y, z, w;
	
	public Point(int x, int y, int z, int w){
		this.x=x;	this.y=y;	this.z=w;	this.w=w;
	}
	
	public Point(Point p){ assign(p); }
	
	public void assign(Point p){
		x=p.x;	y=p.y;	z=p.z;	w=p.w;
	}

	@Override
	public boolean equals(Object obj) {
		if(null == obj) return false;
		if(obj instanceof Point){
			Point p = (Point)obj;
			return p.x==x && p.y==y && p.z==z && p.w==w;
		}
		return false;
	}
}

public class Main {
	private int n, m;				//
	private Point[][][][] pre;		//前向索引,访问与否标记
	private Point s;				//开始位置
	private String[] g;				//图
	private static int[] dx = {1, 0, 0, -1},
						 dy = {0, -1, 1, 0};	//位移方向
	private static String opt = "DLRU";			//操作序列
	
	private boolean cango(int x, int y){
		return x>-1 && x<n && y>-1 && y<m && g[x].charAt(y)!='#';
	}
	
	private Point bfs(){
		pre = new Point[n+1][m+1][n+1][m+1];
		s = new Point(-1, -1, -1, -1);
		/**
		 * -1标记未访问
		 */
		for(int x = 0; x < n; x++) for(int y = 0; y < m; y++) for(int z = 0; z < n; z++)
			for(int w = 0; w < m; w++) pre[x][y][z][w] = new Point(s); 

		Queue<Point> q = new LinkedList<Point>();
		/**
		 * 找到两个点位置
		 */
		outer:	for(int i = 0, cnt = 0; i < n; i++)
					for(int j = 0; j < m; j++) if(g[i].charAt(j) == '*'){
						if(cnt++ == 0){
							s.x = i;	s.y = j;
						}else{
							s.z = i;	s.w = j;
							pre[s.x][s.y][s.z][s.w].assign(s);
							q.add(new Point(s));	break outer;
						}
					}
		/**
		 * 暴力最短路
		 */
		while(!q.isEmpty()){
			Point p = q.remove();
			if(p.x == p.z && p.y == p.w) return p;
			for(int i = 0; i < 4; i++){
				Point np = new Point(p);
				if(cango(np.x+dx[i], np.y+dy[i])){
					np.x+=dx[i];	np.y+=dy[i];
				}
				if(cango(np.z+dx[i], np.w+dy[i])){
					np.z+=dx[i];	np.w+=dy[i];
				}
				if(!np.equals(p) && pre[np.x][np.y][np.z][np.w].x<0){
					q.add(np); 	pre[np.x][np.y][np.z][np.w].assign(p);
				}
			}
		}
		return new Point(-1, -1, -1, -1);
	}
	
	/**
	 * 输出答案
	 */
	private void solve(){
		Point p = bfs();
		if(p.x < 0){
			System.out.println("Sorry");
		}else{
			String ans = "", res="";
			while(!p.equals(s)){
				Point b = new Point(pre[p.x][p.y][p.z][p.w]);

				for(int i = 0; i < 4; i++){
					Point np = new Point(b);
					if(np.x!=p.x || np.y!=p.y){
						np.x+=dx[i];	np.y+=dy[i];
					}
					if(np.z!=p.z || np.w!=p.w){
						np.z+=dx[i];	np.w+=dy[i];
					}
					if(np.equals(p)){
						ans += opt.charAt(i);	
						p = b;		break;
					}
				}
			}
			for(int i = ans.length() - 1; i > -1; i--){
				res += ans.charAt(i);
			}
			System.out.println(res);
		}
	}
	
	private void xtu1187(){
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			n = sc.nextInt();  m = sc.nextInt();
			g = new String[12];
			for(int i = 0; i < n; i++) g[i] = sc.next();
			solve();
		}
	}
	
	public static void main(String[] args) {
		new Main().xtu1187();
	}
}

 

 

题目描述

一个迷宫里,有两个点,你的任务是给出尽可能短的一系列的命令,让这两个点一起执行这些命令能走到一起。如果某个点按某个命令走会走出迷宫或走到障碍上,则忽略这条命令。

输入

输入不超过1000个样例,每个样例第一行有两个整数n,m(2≤n,m≤11),之后n行每行m个字符,'.'表示能走的地方,'#'表示障碍,‘*'表示其中一个点。每个样例之间有一个空行。

输出

每个样例输出一行,包含'U','D','L','R'。'U'表示向上走的命令,'D'表示向下,'L'表示向左,'R'表示向右。要是有多个答案,输出字典序最小的序列。如果无法达到目标,输出“Sorry”(引号不要输出)。

样例输入

4 11
*.##..#..#*
...#..#.#..
.##.#.#.##.
##..###....

4 4
.*..
.###
...*
....

10 10
*.........
#########.
..........
.#########
..........
#########.
..........
.#########
.........*
##########

样例输出

Sorry
LLLUU
LLLLLLLLLUURRRRRRRRRUULLLLLLLLLUURRRRRRRRRDD

posted @ 2014-10-23 19:20  Ramanujan  阅读(278)  评论(0编辑  收藏  举报