您的位置:首页 > 产品设计 > UI/UE

解题报告:hdu1242 zoj1649 Rescue

2012-08-17 23:57 381 查看
                          解题报告:hdu1242 zoj1649

                                              Rescue

                      Time Limit: 2 Seconds       Memory Limit: 65536 KB

Angel was caught by the MOLIGPY! He was put in prison by Moligpy.

The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.

Angel's friends want to save Angel. Their task is: approach Angel.

We assume that "approach Angel" is to get to the position where Angel stays.

When there's a guard in the grid, we must kill him (or her?) to move into the grid.

We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too.

And we are strong enough to kill all the guards.

You have to calculate the minimal time to approach Angel.

(We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)

Input

First line contains two integers stand for N and M.

Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel,

and "r" stands for each of Angel's friend.

Process to the end of the file.

Output

For each test case, your program should output a single integer,

standing for the minimal time needed. If such a number does no exist,

 you should output a line containing "Poor ANGEL has to stay in the prison all his life."

Sample Input

7 8

#.#####.

#.a#..r.

#..#x...

..#..#.#

#...##..

.#......

........

Sample Output

13

题意:在n×m的棋盘似的图形中,求从r到a的最短时间,但要注意不止一个r,

如果遇到“.”的话就消耗一个单位的时间,遇到“x”消耗两个单位的时间,

遇到“#”的话,不能继续前行。

分析:显然这个题目就是求从各个r到达a的最短路径,不过要对于特殊情况进行特判。这样其实有两种做法,第一种就是从r出发找a,这样

其实可以使用dfs(详细见代码一),不过这种做法显然不算优,代码一在hdu可以AC,但是到zoj就是TLE,看来这个方法有点赖过去的嫌疑。

方法二更加优越,从a出发,逆向思维,直到找到第一个r为止(这样说不准确,应该是用时最少的r)。(见代码二)

代码一:

import java.util.Scanner;

public class Main {

    static int INF = 1000000000;

    static int n, m, time, ax, ay, ex, ey;//time其实就是记录最小用时,ax,ay为r所在的位置,ex,ey为a所在的位置

    static int[][] map = new int[205][205];//记录的是从r出发到达(i,j)的最小用时

    static int[][] dis = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };//记录可以移动的四个方向

    static int[][] visited = new int[205][205];//标记从上个点移动到(i,j)这个点这一个移动消耗的时间

    static int dfs(int x, int y, int t) {

        int i, ch, xn, yn;

        if (x == ex && y == ey) {//如果这时已经找到a,递归结束

            if (t < time)

                time = t;

            return 0;

        } else {

            for (i = 0; i < 4; ++i) {//从(x,y)出发,向四个方向移动

                xn = x + dis[i][0];

                yn = y + dis[i][1];

                if (xn < 0 || xn >= n || yn < 0 || yn >= m)//这一步很重要

                    continue;

                if ((visited[xn][yn] == 1 || visited[xn][yn] == 2)//询问这个节点是否合法,且是否用时更少

                        && t + visited[xn][yn] <= time) {

                    if (map[xn][yn] == -1 || t + visited[xn][yn] <= map[xn][yn]) {

                        map[xn][yn] = t + visited[xn][yn];

                        ch = visited[xn][yn];//保存下visited[xn][yn]的值

                        visited[xn][yn] = -1;//更改visited[xn][yn]保证在下面的递归过程中,不能在往回走

                        dfs(xn, yn, t + ch);

                        visited[xn][yn] = ch;//将visited[xn][yn]这个值进行还原,因为可能在下面的运行过程中还有可能用到

                        //也就是因为可能一条路线可能会被多次查询,所以才有可能会TLE

                    }

                }

            }

        }

        return 0;

    }

    public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);

        char[] str = new char[203];

        while (scan.hasNext()) {

            time = INF;

            n = scan.nextInt();

            m = scan.nextInt();

            //初始化

            for (int i = 0; i <= n + 2; i++) {

                for (int j = 0; j <= m + 2; j++) {

                    map[i][j] = -1;

                    visited[i][j] = -1;

                }

            }

            //读入这个图形,同时找到ax,ay,ex,ey,对visited数组进行合法化初始化

            for (int i = 0; i < n; i++) {

                String st = scan.next();

                str = st.toCharArray();

                for (int j = 0; j < m; j++) {

                    if (str[j] == '.')

                        visited[i][j] = 1;

                    else if (str[j] == 'x')

                        visited[i][j] = 2;

                    else if (str[j] == 'r') {

                        ax = i;

                        ay = j;

                    } else if (str[j] == 'a') {

                        ex = i;

                        ey = j;

                        visited[i][j] = 1;

                    }

                }

            }

            dfs(ax, ay, 0);

            if (time != INF)

                System.out.println(time);

            else

                System.out

                        .println("Poor ANGEL has to stay in the prison all his life.");

        }

    }

}

代码二

import java.util.Comparator;

import java.util.PriorityQueue;

import java.util.Scanner;

class point {

    int x, y, step;//定义一个顶点类,坐标为(x,y),用step表示到达该节点

}

public class Mainhdu1242 {

    static int n, m, bx, by;

    static char[][] map = new char[202][202];//记录每个点的状态

    static int[][] dis = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };

    static void bfs() {

        PriorityQueue<point> queue = new PriorityQueue<point>(1,//用到了优先队列,把每个结点用step进行排序

                new Comparator<point>() {

                    public int compare(point a, point b) {

                        if (a.step < b.step)

                            return -1;

                        else if (a.step == b.step) {

                            return 0;

                        } else {

                            return 1;

                        }

                    }

                });

        point t = new point();

        t.x = bx;

        t.y = by;

        t.step = 0;

        queue.offer(t);

        while (!queue.isEmpty()) {

            point q = queue.poll();

            for (int i = 0; i < 4; i++) {

                point tt = new point();//注意不能直接写成point tt=q,应为这样传递的是指针,在改变tt的参数的同时也改变了q

                tt.x = q.x + dis[i][0];

                tt.y = q.y + dis[i][1];

                tt.step = q.step + 1;

                i
8af6
f (tt.x < 0 || tt.x >= n || tt.y < 0 || tt.y >= m

                        || map[tt.x][tt.y] == '#')

                    continue;

                else if (map[tt.x][tt.y] == 'r') {

                    System.out.println(tt.step);

                    return;

                } else if (map[tt.x][tt.y] == 'x')

                    tt.step++;

                map[tt.x][tt.y] = '#';//将查询过的点标记为不能再次查询

                queue.offer(tt);//把查询到的点加到队列中

            }

        }

        System.out

                .println("Poor ANGEL has to stay in the prison all his life.");

        return;

    }

    public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);

        while (scan.hasNext()) {

            n = scan.nextInt();

            m = scan.nextInt();

            for (int i = 0; i < n; i++) {

                String str = scan.next();

                map[i] = str.toCharArray();

                for (int j = 0; j < m; j++) {

                    if (map[i][j] == 'a') {

                        bx = i;

                        by = j;

                        break;

                    }

                }

            }

            bfs();

        }

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息