链接:



Ignatius and the Princess I

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10006    Accepted Submission(s): 3004
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
 
Author
Ignatius.L
 


题意:


给你一个 N*M 的图, 要你从第一个点走到最后一个点【从左上角走到右下角】
只可以按照上下左右四个方向走

. : 代表可以走
 
X :  表示是墙,不可以走

n :  代表这里有一个怪兽,打败怪兽用时 n

每走一步耗时 1 .

如果能到达,则输出最小时间和每一步的走法
不能到达输出。。。
具体输出看样例。

注意:保证起点没有怪兽,终点不是墙。【也就是说终点可能有怪兽】




算法:优先队列+BFS 【本质Dijkstra】


思路:


很裸的最短路了,但是不熟悉优先队列,用自己的笨方法错了很久。


正解思路

由于是用的优先队列+BFS 为了方便输出路径,所以从终点开始搜索
从起点开始也可以,只是不方便,要么递归输出路径点击打开链接
要么定义一个数组来维护,使得本来就很复杂了的简单题目越发变得复杂起来。

定义一个优先队列,包含了位置和当前位置到达终点的最短时间。
优先队列保证时间短的先出队。。。
//定义优先队列:对于入队了的点,先出队的是时间少的,那么第一个到达终点的就是结果
struct Node{
int x,y; //当前到达的点
int time; //耗费的时间 bool operator < (const Node &b) const{
return b.time < time;
}
};

关于优先队列的重载一直不是很清楚。。。

下面我是这么理解的,每次新加入一个点 b ,不管他们的 x 和 y 也就是默认关于 x 和 y 按照普通的队列定义,先进先出

然后优先考虑 time ,b.time 与原来的队列中的每一个 time 比较【从队首往队伍遍历】如果一旦遇到了 b.time < time
那么就把 " b 插入到当前遍历到的位置". 有待路过的大神详细指教下。
 
由于优先队列保证了按照时间少的先出队,那么第一个遍历到起点的一定是所求的最短路了。
后面可能会有其它的路,但是不会比这条路更优。【special judge】

下面我们考虑输出问题:定义一个先驱结构体记录每一个点的前一个点的位置就好了。
注意:由于搜索的时候为了方便输出路径是从终点往起点搜索的,那么先驱中记录的点其实是实际走的过程中的下一个点。

此题参考博客:点击打开链接


 
我的开始错误思路分析

开始没有想到用优先队列搜索,由于前面做过 BFS 倒水问题POJ 3414 Pots【bfs模拟倒水问题】 也是要模拟输出路径
就感觉很像,其实错了。。。然后按照这题的思路写。
也考虑了会有多条路到达,但是想到点很少才 100*100 就准备直接暴力搜索完所有的点。
开始想的是,一旦到达终点就和原来的比较看能否更优【我以为那个方法会多次到达终点】
其实我入队的时候标记了,出队却没有标记,所以最多只可能到达一次终点,根本不可能多次到达终点,更新最小时间。
但是样例出来了,自己怎么想也想不出错误我的错误思路代码

后来请教了下南城边,他给我指出了上面提到的问题,更本不可能更新最小时间。因为按照上面的写法,终点只可能入队和出队一次。
然后我又准备用最短路的思想模拟,但是还是准备在上面的基础上改一下,于是每一个点出队我也标记了下,这样保证了终点可以多次遍历到
但是这样一来就无法解决跳出 BFS 问题,于是我想到每一个点最多被上下左右的点走一次,那么是不是标记每一个点最多入队四次就可以了呢?
样例同样出来了,结果还是 WA 。。。
想了下:可能是我虽然标记了入队四次,但是可能这四次都是由同一个点到达的,那么也和标记一次没有分别了,还是无法解决上面的更新最短时间问题。

所以:最终还是只能按照最短路的思想遍历。

很裸的题目了,本来只是打算练下手,结果还是做了很久。菜鸟要努力 Fighting !!!Come on

code:

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std; const int maxn = 110;
const int INF = maxn*maxn*10; int map[maxn][maxn]; //记录图
int vis[maxn][maxn]; //标记入队
char str[maxn];
int n,m; int dir[4][2] = {0,1, 0,-1, -1,0, 1,0}; //定义优先队列:对于入队了的点,先出队的是时间少的,那么第一个到达终点的就是结果
struct Node{
int x,y; //当前到达的点
int time; //耗费的时间 bool operator < (const Node &b) const{
return b.time < time;
}
}; //每一个点的前驱, 由于是逆向搜索的, 所以记录的其实是当前点的下一个点了
struct Pre{
int px, py;
}pre[maxn][maxn]; void bfs()
{
Node now, next;
priority_queue<Node> q;
while(!q.empty()) q.pop(); now.x = n; now.y = m; //从终点走向起点
now.time = map[n][m]; //注意:终点也可能会有怪兽
pre[n][m].px = -1; //输出边界
q.push(now); memset(vis, 0, sizeof(vis)); //为方便快速输出路径, 从终点往起点找
vis[n][m] = 1; //标记终点入队 while(!q.empty())
{
now = q.top(); q.pop(); if(now.x == 1 && now.y == 1) //一旦到达起点
{
printf("It takes %d seconds to reach the target position, let me show you the way.\n", now.time);
int time = 1;
int x = now.x, y = now.y; //当前的位置
int nx = pre[x][y].px, ny = pre[x][y].py; //下一个位置
while(pre[x][y].px != -1) //不停的找前驱
{
printf("%ds:(%d,%d)->(%d,%d)\n", time++, x-1, y-1, nx-1, ny-1);
while(map[nx][ny]--) //如果有怪兽
{
printf("%ds:FIGHT AT (%d,%d)\n", time++, nx-1, ny-1);
}
x = nx; y = ny; //继续查找下一个点
nx = pre[x][y].px, ny = pre[x][y].py;
}
printf("FINISH\n");
return; //结束
} for(int i = 0; i < 4; i++)
{
next.x = now.x+dir[i][0];
next.y = now.y+dir[i][1]; if(map[next.x][next.y] >= 0 && !vis[next.x][next.y]) //当前点可以走,并且没有入队过
{
vis[next.x][next.y] = 1; //标记入队 next.time = now.time + 1 + map[next.x][next.y];
pre[next.x][next.y].px = now.x; //前驱记录
pre[next.x][next.y].py = now.y; q.push(next);
}
}
} printf("God please help our poor hero.\n"); //不能到达
printf("FINISH\n");
return;
} int main()
{
while(scanf("%d%d", &n,&m) != EOF)
{
gets(str);
for(int i = 0; i <= n+1; i++) //周围加边
for(int j = 0; j <= m+1; j++)
map[i][j] = -1; char c;
for(int i = 1; i <= n; i++) //输出的时候注意 -1 处理下
{
for(int j = 1; j <= m; j++)
{
scanf("%c", &c);
if(c != 'X')
{
if(c == '.') map[i][j] = 0;
else map[i][j] = c-'0';
}
}
gets(str);
} bfs();
}
return 0;
}

 

hdu 1026 Ignatius and the Princess I【优先队列+BFS】的更多相关文章

  1. hdu 1026 Ignatius and the Princess I(优先队列+bfs+记录路径)

    以前写的题了,现在想整理一下,就挂出来了. 题意比较明确,给一张n*m的地图,从左上角(0, 0)走到右下角(n-1, m-1). 'X'为墙,'.'为路,数字为怪物.墙不能走,路花1s经过,怪物需要 ...

  2. HDU 1026 Ignatius and the Princess I(BFS+优先队列)

    Ignatius and the Princess I Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d &am ...

  3. hdu 1026 Ignatius and the Princess I(bfs)

    Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  4. HDU 1026 Ignatius and the Princess I (BFS)

    题目链接 题意 : 从(0,0)点走到(N-1,M-1)点,问最少时间. 思路 : BFS..... #include <stdio.h> #include <string.h> ...

  5. hdu 1026 Ignatius and the Princess I(BFS+优先队列)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1026 Ignatius and the Princess I Time Limit: 2000/100 ...

  6. hdu 1026 Ignatius and the Princess I

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1026 Ignatius and the Princess I Description The Prin ...

  7. hdu 1026:Ignatius and the Princess I(优先队列 + bfs广搜。ps:广搜AC,深搜超时,求助攻!)

    Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  8. hdu 1026 Ignatius and the Princess I (bfs+记录路径)(priority_queue)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1026 Problem Description The Princess has been abducted ...

  9. hdu 1026 Ignatius and the Princess I 搜索,输出路径

    Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

随机推荐

  1. HDU 1870 愚人节的礼物

    题解:简单的数括号问题…… #include <cstdio> char s[1005]; int main(){ while(scanf("%s",s)!=EOF){ ...

  2. IOS开发新手教程(一)-数据类型和运算符

    OC语法入门(一) 数据类型和运算符 1.1凝视 凝视和其它语言一样,同意单行 ,多行凝视,一份规范的代码里面须要有一些正式的凝视,例如以下凝视: /* 这是多行 凝视 */ //这是多行凝视 OC语 ...

  3. PE框架学习之道:PE框架——style的配置

    1.在style.xml中定义style     <style id="NumberStyle"> <setting> <param name=&qu ...

  4. Android中图片处理相关问题

    在Android的开发中,我们经常回去处理一些图片相关的问题,比如当加载图片到内存中产生的OOM(OutOfMemory)异常.图片加载到内存中占多大内存的问题.jpg png两种常见的图片的原理及区 ...

  5. ansible笔记

    ansible 资料 ansible 配置 ansible inventory配置文件 ansible模块 http://www.cnblogs.com/iois/p/6216936.html ans ...

  6. s3c2440栈分配情况(fl2440裸机 stack)

    //2440INIT.S ;The location of stacks UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~ SVCStac ...

  7. linux驱动: 如何向模块传递参数, module_param和module_param_array

    如何向模块传递参数,Linux kernel 提供了一个简单的框架.    1.  module_param(name, type, perm); name 既是用户看到的参数名,又是模块内接受参数的 ...

  8. linux shell: 搜索字符串,剔除包含特定字符的行

    搜索代码中出现CONFIG_BOOTARGS的行,但又不希望有#define和#undef, 暂时不知带如何直接用一个语句做到,因此用了如下三个语句. find . -type f | xargs g ...

  9. Spring AOP报错

    八月 01, 2016 10:08:48 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRe ...

  10. JavaScript基础知识----document对象

    对象属性document.title                 //设置文档标题等价于HTML的<title>标签document.bgColor               //设 ...