链接:



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. http://download.qt-project.org/archive/qt/4.5/qt-all-opensource-src-4.5.2.tar.bz2

    Index of /archive/qt/4.5 http://download.qt-project.org/archive/qt/4.5/qt-all-opensource-src-4.5.2.t ...

  2. readv和writev函数

    readv 和 writev 函数用于在一次函数调用中读.写多个非连续缓冲区.有时也将这两个函数称为散布读和聚集写. #include <sys/uio.h> ssize_t readv( ...

  3. 用 jQuery Masonry 插件创建瀑布流式的页面

    瀑布流式的页面,最早我是在国外的一个叫 Pinterest 的网站上看到,这个网站爆发,后来国内的很多网站也使用了这种瀑布流方式来展示页面(我不太喜欢瀑布流这个名字). 我们可以使用 jQuery 的 ...

  4. Linux虚拟机与外面系统ping不通,或者连不上网

    很多其它具体文档:http://download.csdn.net/download/zml_2015/8843061 非常多人在做linux课程设计的时候,用的linux虚拟机与外面的系统ping不 ...

  5. URL中含有+号,出现错误“请求筛选模块被配置为拒绝包含双重转义序列的请求”的解决方法

    搜索关键词中含空格,提交后被自动转成了“+”号,报如下错误: HTTP 错误 404.11 - Not Found 请求筛选模块被配置为拒绝包含双重转义序列的请求. 解决方法: 在web.config ...

  6. 10个JavaScript小技巧

    1.变量转换 看起来很简单,但据我所看到的,使用构造函数,像Array()或者Number()来进行变量转换是常用的做法.始终使用原始数据类型(有时也称为字面量)来转换变量,这种没有任何额外的影响的做 ...

  7. C#关键字列表

  8. 说说Xcode4中xib绑定的原理

    最开始的是时候始终没有弄明白xib文件中的绑定关系.经过一周的开发体验终于有一些理解与收获. Xib文件就是MVC模式中的View这个层的界面显示布局的信息.即类似Asp.net的aspx文件或者ja ...

  9. JQuery 实现返回顶部效果

    首先要里了解一下几个知识 $(window).scrollTop() ---滚动条距顶部距离 fadeIn() 方法使用淡入效果来显示被选元素,假如该元素是隐藏的. fadeOut() 方法使用淡出效 ...

  10. 基于visual Studio2013解决C语言竞赛题之0407最大值最小值

      题目 解决代码及点评 这道题考察循环和比较 /*********************************************************************** ...