500年前,Jesse是我国最卓越的剑客。他英俊潇洒,而且机智过人^_^。
突然有一天,Jesse心爱的公主被魔王困在了一个巨大的迷宫中。Jesse听说这个消息已经是两天以后了,他知道公主在迷宫中还能坚持T天,他急忙赶到迷宫,开始到处寻找公主的下落。 时间一点一点的过去,Jesse还是无法找到公主。最后当他找到公主的时候,美丽的公主已经死了。从此Jesse郁郁寡欢,茶饭不思,一年后追随公主而去了。T_T 500年后的今天,Jesse托梦给你,希望你帮他判断一下当年他是否有机会在给定的时间内找到公主。
他会为你提供迷宫的地图以及所剩的时间T。请你判断他是否能救出心爱的公主。

 

    题目包括多组测试数据。 每组测试数据以三个整数N,M,T(0<n, m<=20,0<t<=100000)开头,分别代表迷宫的长和高,以及公主能坚持的天数。 紧接着有M行,N列字符,由".","*","P","S"组成。其中 "." 代表能够行走的空地。 "*" 代表墙壁,Jesse不能从此通过。 "P" 是公主所在的位置。 "S" 是Jesse的起始位置。 每个时间段里Jesse只能选择“上、下、左、右”任意一方向走一步。 输入以0 0 0结束。

 

样例输入


m = 4, n = 4, t = 10
迷宫图如下
....
....
....
S**P

 

样例输出


0

package search;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * 解题思路:以P为根节点,获取相邻节点作为子节点,以此类推,可以获取到最短路径,到达最短路径的深度即为花费的最短时间
 *
 */
public class RescuePrincess {
    // 移动方向
    int[][] move = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };
    //终点,以此为基,遍历前面的节点,还原最短路径
    Node lastNode;
    //通过广度优先遍历,获取最短路径
    public int getBFS(char[][] visited, int t, int n, int m) {
        if (n <= 0 || n > 20 || m <= 0 || m > 20 || t <= 0
                || visited.length != m || visited[0].length != n) {
            return -1;
        }
        Node hero=getFirstNode(visited);
        if(hero==null){
            return -1;
        }
        Queue<Node> path = new LinkedList<Node>();
        path.offer(hero);
        while (!path.isEmpty()) {
            Node temp = path.poll();
            if ((temp.level + 1) > t) {
                return -1;
            }
            for (int i = 0; i < move.length; i++) {
                //当当前点坐标在边上时,若move方向为负则排除掉
                if ((temp.x == 0 && move[i][1] < 0)
                        || (temp.y == 0 && move[i][0] < 0)
                        || (temp.x == (visited[0].length - 1) && move[i][1] > 0)
                        || (temp.y == (visited.length - 1) && move[i][0] > 0)) {
                    continue;
                }
                Node p = new Node(temp.x + move[i][1], temp.y + move[i][0],
                        temp.level + 1);
                if (visited[p.y][p.x] == '.') {
                    visited[p.y][p.x] = '0';
                    p.pre = temp;
                    path.offer(p);
                } else if (visited[p.y][p.x] == 'S') {
                    visited[p.y][p.x] = '0';
                    p.pre = temp;
                    this.lastNode = p;
                    return 0;
                }
            }
        }
        return -1;
    }
    //获取开始节点P的坐标位置
    public Node getFirstNode(char[][] visited){
        Node hero=new Node(0,0,0);
        for (int i = 0; i < visited.length; i++) {
            for (int j = 0; j < visited[0].length; j++) {
                if ('P' == visited[i][j]) {
                    hero.x = j;
                    hero.y = i;
                    hero.level = 0;
                    visited[i][j] = '0';
                    return hero;
                }
            }
        }
        return null;
    }
    //打印最短路径
    public void printPath(){
        Node temp=this.lastNode;
        Stack<Node> s=new Stack<Node>();
        while(temp!=null){
            s.push(temp);
            temp=temp.pre;
        }
        while(!s.isEmpty()){
            System.out.println(s.pop().toString());
        }
    }
    public static void main(String[] args) {
        int N = 4;
        int M = 7;
        int T = 10;
        char a[][] = { { 'S', '.', '*', '.' },
                { '.', '.', '*', '.' },
                { '.', '.', '.', '.' }, 
                { '.', '.', '*', '.' },
                { '.', '.', '.', '.' },
                { '.', '.', '*', '.'},
                { '.', '*', '*', 'P' } };
        RescuePrincess rp = new RescuePrincess();
        int res=rp.getBFS(a, T, N, M);
        if(res==0)
            rp.printPath();
        else
            System.out.println("公主拯救失败");
    }

    class Node {
        //x、y为坐标,level为坐标点所在树的深度
        int level, x, y;
        //指向上一个节点
        Node pre;
        public Node(int x, int y, int level) {
            this.x = x;
            this.y = y;
            this.level = level;
        }

        public String toString() {
            return "(" + this.x + "," + this.y + "," + this.level + ")";
        }
    }
}