hdu 1026 Ignatius and the Princess I (bfs)

来源:互联网 发布:水晶机巧矩阵黄晶 编辑:程序博客网 时间:2024/06/11 02:20

Ignatius and the Princess I

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Special Judge

Problem Description
The Princess has been abducted by the BEelzebub feng5166, our hero Ignatius has to rescue our pretty Princess. Now he gets into feng5166’s castle. The castle is a large labyrinth. To make the problem simply, we assume the labyrinth is a N*M two-dimensional array which left-top corner is (0,0) and right-bottom corner is (N-1,M-1). Ignatius enters at (0,0), and the door to feng5166’s room is at (N-1,M-1), that is our target. There are some monsters in the castle, if Ignatius meet them, he has to kill them. Here is some rules:

1.Ignatius can only move in four directions(up, down, left, right), one step per second. A step is defined as follow: if current position is (x,y), after a step, Ignatius can only stand on (x-1,y), (x+1,y), (x,y-1) or (x,y+1).
2.The array is marked with some characters and numbers. We define them like this:
. : The place where Ignatius can walk on.
X : The place is a trap, Ignatius should not walk on it.
n : Here is a monster with n HP(1<=n<=9), if Ignatius walk on it, it takes him n seconds to kill the monster.

Your task is to give out the path which costs minimum seconds for Ignatius to reach target position. You may assume that the start position and the target position will never be a trap, and there will never be a monster at the start position.

Input
The input contains several test cases. Each test case starts with a line contains two numbers N and M(2<=N<=100,2<=M<=100) which indicate the size of the labyrinth. Then a N*M two-dimensional array follows, which describe the whole labyrinth. The input is terminated by the end of file. More details in the Sample Input.

Output
For each test case, you should output “God please help our poor hero.” if Ignatius can’t reach the target position, or you should output “It takes n seconds to reach the target position, let me show you the way.”(n is the minimum seconds), and tell our hero the whole path. Output a line contains “FINISH” after each test case. If there are more than one path, any one is OK in this problem. More details in the Sample Output.

Sample Input
5 6
.XX.1.
..X.2.
2…X.
…XX.
XXXXX.
5 6
.XX.1.
..X.2.
2…X.
…XX.
XXXXX1
5 6
.XX…
..XX1.
2…X.
…XX.
XXXXX.

Sample Output
It takes 13 seconds to reach the target position, let me show you the way.
1s:(0,0)->(1,0)
2s:(1,0)->(1,1)
3s:(1,1)->(2,1)
4s:(2,1)->(2,2)
5s:(2,2)->(2,3)
6s:(2,3)->(1,3)
7s:(1,3)->(1,4)
8s:FIGHT AT (1,4)
9s:FIGHT AT (1,4)
10s:(1,4)->(1,5)
11s:(1,5)->(2,5)
12s:(2,5)->(3,5)
13s:(3,5)->(4,5)
FINISH
It takes 14 seconds to reach the target position, let me show you the way.
1s:(0,0)->(1,0)
2s:(1,0)->(1,1)
3s:(1,1)->(2,1)
4s:(2,1)->(2,2)
5s:(2,2)->(2,3)
6s:(2,3)->(1,3)
7s:(1,3)->(1,4)
8s:FIGHT AT (1,4)
9s:FIGHT AT (1,4)
10s:(1,4)->(1,5)
11s:(1,5)->(2,5)
12s:(2,5)->(3,5)
13s:(3,5)->(4,5)
14s:FIGHT AT (4,5)
FINISH
God please help our poor hero.
FINISH

题目就是十分耿直的迷宫最短路(时间)。只是多了打怪和按格式输出路径的细节。

起点没有怪。

虽然做过一些bfs,但需要输出路径的bfs还真没做过……

合理的解题思路是把走过的路径存在一个图里,这里另开了一个图step[M][M](M = 105,其实直接存到原来读图用的图里也没啥问题),每经过一次bfs,入队的节点在step上的对应位置就存放它的上一个路径节点,最后再循着路径倒回去再输出来(dfs部分)。

PS:

1. 由于bfs会判重,整个图所有可走节点最多只会入队一次,因此不必担心路径节点会被覆盖的问题,因为最多只会赋一次值。2. 存图要倒着存,图的当前位置只能用于存放上一节点,因为这个路径是唯一的,但若存放下一节点最多就有四种可能,故不可行。

作为hdu第一版,这道题算是一道综合性比较强的简单题吧,基本上基础的点都有涉及到(基础迷宫最短路,打怪耗时间需要开优先队列,输出最短路径,比较墨迹的输出格式【不】)。因为以前做过一道直接在结构体里存字符串的题,一开始就直接耿直的在结构体里面开数组开的M*M,导致bfs过程中的赋值开销太大,然后我就被教做人了。也是头一次经历bfs超时这种事情……你WA也好啊我也认了你给我个T……懵逼了好久TAT

后来看了眼和我解法相似的某题解,抱着“hdu第一版的水题,数据应该也很水”的心态把数组开小成了1000,然后就过了……过了……不过时间仍然是接近卡过,650+ms.

然后想是不是开vector会好一点。

不过想归想,这样还是不能完全防止比较极端的数据的超时问题,于是就有了存图。

瞬间变成0ms.

我好渣啊Orz……

#include <iostream>#include <vector>#include <cstdio>#include <string>#include <cstring>#include <queue>#include <algorithm>#define MAX 100005#define LL long long#define M 105#define INF 0x7f7f7f7fusing namespace std;struct node{    int x, y, time, p;    void Set(int a, int b)    {        x += a, y += b, time += 1, p = 0;    }    bool friend operator < (const node &a, const node &b)    {        return a.time > b.time;    }}st, t, tmp, step[M][M];int n, m, cnt, to[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};bool vis[M][M];char g[M][M];void bfs(){    memset(vis, false, sizeof(vis));    priority_queue<node> Q;    Q.push(st);    vis[0][0] = true;    while(!Q.empty())    {        tmp = Q.top();        Q.pop();        for(int i = 0; i < 4; i++)        {            t = tmp;            t.Set(to[i][0], to[i][1]);            if(t.x >= 0 && t.x < n && t.y >= 0 && t.y < m && !vis[t.x][t.y] && g[t.x][t.y] != 'X')            {                if(g[t.x][t.y] >= '1' && g[t.x][t.y] <= '9')//打怪                {                    t.time += g[t.x][t.y] - '0';                    t.p = g[t.x][t.y] - '0';                }                Q.push(t);                vis[t.x][t.y] = true;                step[t.x][t.y] = tmp;//存图            }            if(t.x == n - 1 && t.y == m - 1)                return;        }    }    return;}void dfs(node a){    if(!step[a.x][a.y].x && !step[a.x][a.y].y && !a.x && !a.y)//判断是否倒回起点位置    {        printf("It takes %d seconds to reach the target position, let me show you the way.\n", t.time);        return;    }    dfs(step[a.x][a.y]);    printf("%ds:(%d,%d)->(%d,%d)\n", ++cnt, step[a.x][a.y].x, step[a.x][a.y].y, a.x, a.y);    for(int j = 0; j < a.p; j++)        printf("%ds:FIGHT AT (%d,%d)\n", ++cnt, a.x, a.y);    return;}int main(){    while(~scanf("%d %d", &n, &m))    {        for(int i = 0; i < n; i++)  scanf("%s", g[i]);        bfs();        if(!(t.x == n - 1 && t.y == m - 1))            printf("God please help our poor hero.\n");        else        {            cnt = 0;            dfs(t);        }        printf("FINISH\n");    }    return 0;}

运行结果:
这里写图片描述

0 0
原创粉丝点击