Ignatius and the Princess I

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10541    Accepted Submission(s): 3205
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
.XX..
..X..
...X.
...XX.
XXXXX. .XX..
..X..
...X.
...XX.
XXXXX1 .XX...
..XX1.
...X.
...XX.
XXXXX.
Sample Output
It takes  seconds to reach the target position, let me show you the way.
1s:(,)->(,)
2s:(,)->(,)
3s:(,)->(,)
4s:(,)->(,)
5s:(,)->(,)
6s:(,)->(,)
7s:(,)->(,)
8s:FIGHT AT (,)
9s:FIGHT AT (,)
10s:(,)->(,)
11s:(,)->(,)
12s:(,)->(,)
13s:(,)->(,)
FINISH
It takes seconds to reach the target position, let me show you the way.
1s:(,)->(,)
2s:(,)->(,)
3s:(,)->(,)
4s:(,)->(,)
5s:(,)->(,)
6s:(,)->(,)
7s:(,)->(,)
8s:FIGHT AT (,)
9s:FIGHT AT (,)
10s:(,)->(,)
11s:(,)->(,)
12s:(,)->(,)
13s:(,)->(,)
14s:FIGHT AT (,)
FINISH
God please help our poor hero.
FINISH
Author
Ignatius.L
 
Recommend
We have carefully selected several similar problems for you:  1072 1180 1253 1242 1240 

 
目录:
 
 
2014/1/3 17:10:00 
  一开始不知道这道题要用广搜bfs做,上来直接用了深搜dfs(广搜实在是还不会用),加起来做了近4个小时,最后提交给了我一个超时……
  对着一位同样用dfs做的却AC(耗时900+MS)的大神的代码(博客地址:http://blog.csdn.net/qhc_20130731/article/details/9078149)改了改,到后来代码直接看不懂了!
  贴上我的代码,愿有看到的筒靴帮一把!感激不尽!
  测试数据正确,提交超时
 
 #include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
struct Way{
int x;
int y;
bool ism;
}way[]; //存储每一秒走到的位置,及有没有怪物
char maze[][];
bool isv[][];
int dx[]={,,,-};
int dy[]={,,-,};
int curx,cury;
int endx,endy;
int N,M;
int _min;
int dfs(int curx,int cury,int s) //当前的位置以及走到这个位置用的时间(秒)和方向
{
int n=;
if(curx==N- && cury==M-){
//到达终点
_min=s;
if(''<=maze[curx][cury] && maze[curx][cury]<=''){
//如果当前位置有怪物
int t; //怪物的HP
t=maze[curx][cury]-'';
for(int i=;i<=t;i++){
way[s-i].x=curx;
way[s-i].y=cury;
way[s-i].ism=true;
}
}
else{
//当前位置没有怪物
way[s].x=curx;
way[s].y=cury;
way[s].ism=false;
}
return s;
}
//没有走到终点的时候
for(int i=;i<;i++){
int nx = curx+dx[i];
int ny = cury+dy[i];
if(<=nx && nx<=N- && <=ny && ny<=M- //如果没有越界
&& maze[nx][ny]!='X' //下一步没有陷阱
&& !isv[nx][ny] //下一步没走过
){
int t; //有怪物的话存储怪物的HP,否则为1
if(''<=maze[nx][ny] && maze[nx][ny]<=''){
t=int(maze[nx][ny]-'')+;
}
else{
t=;
}
if(s+t>=_min) continue; //再次剪枝
isv[nx][ny]=true;
int tt;
if( tt=dfs(nx,ny,s+t) ){
//找到最短路
n=tt;
way[s].x=curx;
way[s].y=cury;
way[s].ism=false;
if(''<=maze[curx][cury] && maze[curx][cury]<=''){
//如果当前位置有怪物
int t; //怪物的HP
t=maze[curx][cury]-'';
for(int i=;i<=t;i++){
way[s-i].x=curx;
way[s-i].y=cury;
way[s-i].ism=true;
}
}
}
isv[nx][ny]=false;
}
}
return n;
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF){ //开始一个新的地图
getchar();
memset(isv,,sizeof(isv)); //初始化
_min=;
curx=,cury=; //初始化开始、终点位置
endx=N-,endy=M-;
for(int i=;i<N;i++){
for(int j=;j<M;j++){
scanf("%c",&maze[i][j]);
}
getchar();
}
int n; //如果能走到终点的话,接收最短步数
isv[][]=true;
n=dfs(curx,cury,);
if(n){
//能走
printf("It takes %d seconds to reach the target position, let me show you the way.\n",n);
for(int i=;i<n;i++){
if(way[i].ism){
//如果有怪物
printf("%ds:FIGHT AT (%d,%d)\n",i+,way[i].x,way[i].y);
}
else {
printf("%ds:(%d,%d)->(%d,%d)\n",i+,way[i].x,way[i].y,way[i+].x,way[i+].y);
}
}
}
else{
//走不到终点
printf("God please help our poor hero.\n");
}
printf("FINISH\n");
}
return ;
}

2014/1/16 22:51:00

  重写了这道题,用广搜方法终于提交AC了。
  bfs广搜题。
  这道题着实费了我不少力气,写了3个小时,原因是这道题在bfs基本框架的基础上改动比较大,对刚刚熟悉广搜做法的我来说有些吃力。而且中间由于思路想的不对,走了弯路,花费了不少时间修改。事实证明,思路很重要,想的有一点偏差,就要付出双倍时间的代价为这点偏差买单。另外,程序实现能力还需要提高,有些思路不是想不到,而是觉得自己实现不了而下意识的规避了。如果什么程序实现能力变强了,思考问题就会用这种语言去想,等到真正去实现的时候,自然就水到渠成。
  好了扯远了,回到这道题,题目大意为:骑士(地图左上角)要去救公主(地图右下角),而他们之间(地图上)有3种物体,‘.’为路,可以通过;‘X’为墙,不能通过;'1'~'9'数字为怪物的血量num。骑士遇到怪物,要停留num秒,求骑士能否到达公主的位置,如果能到达,输出最短路径的长度,并输出路径,如果不能到,输出特定语句。
  思路是bfs中遇到怪物的时候节点位置(x,y)不作处理,而只将当前节点步数(step)加1,将它重新入队,同时怪物血量-1(注意这里要对备用地图处理),直到减为0才能通过,这期间,该点一直在怪物位置。关于路径的处理,广搜的时候记录下路径,退出广搜后从终点处开始还原路径。之后输出路径。
  难点是遇到怪物时的处理和路径的还原。
 
 #include <iostream>
#include <string.h>
#include <queue>
using namespace std;
char a[][]; //记录地图
char b[][]; //备用地图,用以修改
int isv[][]; //记录访问过没有
int way[][]; //记录路径
int dx[] = {,,,-};
int dy[] = {,,-,};
int N,M;
struct NODE{
int x;
int y;
int step;
};
bool judge(int x,int y)
{
if( x< || y< || x>N || y>M ) //出界
return ;
if( isv[x][y] ) //走过
return ;
if( a[x][y]=='X' ) //遇到墙
return ;
return ;
}
int bfs(int x,int y) //返回到达终点的时间(包括在终点停留的时间)
{
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
b[i][j] = a[i][j];
queue <NODE> q;
NODE cur,next;
cur.x = x;
cur.y = y;
cur.step = ;
q.push(cur); //第一个节点入队
while(!q.empty()){
cur = q.front();
q.pop(); //队首出队
if( cur.x==N && cur.y==M ){
int num = ;
if(''<=b[cur.x][cur.y] && b[cur.x][cur.y]<='')
num = b[cur.x][cur.y] - '';
return cur.step + num;
}
if(''<=b[cur.x][cur.y] && b[cur.x][cur.y]<=''){ //遇到怪物,step+1,位置不变,入队
next.x = cur.x;
next.y = cur.y;
next.step = cur.step + ;
q.push(next);
if(b[cur.x][cur.y]=='')
b[cur.x][cur.y] = '.';
b[cur.x][cur.y]--;
continue;
}
for(int i=;i<;i++){
int nx = cur.x + dx[i];
int ny = cur.y + dy[i];
if(judge(nx,ny)) //判定
continue;
//可以走
next.x = nx;
next.y = ny;
way[nx][ny] = i; //记录路径
isv[nx][ny] = true; //记录访问过
next.step = cur.step + ;
q.push(next);
}
}
return ;
}
int main()
{
while(cin>>N>>M){
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
cin>>a[i][j];
memset(isv,,sizeof(isv));
isv[][] = true;
int step = bfs(,);
if(step){ //到达终点
NODE way_node[];
int cx=N,cy=M;
for(int i=step;i>=;i--){ //根据way[][]还原路径
way_node[i].x = cx;
way_node[i].y = cy;
int num=;
if(''<=a[cx][cy] && a[cx][cy]<='') //如果该位置有怪物
num = a[cx][cy] - '';
for(int j=num;j>=;j--){
way_node[i-j].x = cx;
way_node[i-j].y = cy;
}
if(num){
i-=num;
}
switch(way[cx][cy]){ //没有怪物则继续还原路径
case :cy--;break;
case :cx--;break;
case :cy++;break;
case :cx++;break;
default:break;
}
}
//输出结果
cout<<"It takes "<<step<<" seconds to reach the target position, let me show you the way."<<endl;
for(int i=;i<=step;i++){
cout<<i<<"s:("<<way_node[i-].x-<<','<<way_node[i-].y-<<")->("<<way_node[i].x-<<','<<way_node[i].y-<<')'<<endl;
cx = way_node[i].x;
cy = way_node[i].y;
if(''<=a[cx][cy] && a[cx][cy]<=''){
int num = a[cx][cy] - '';
for(int j=;j<=num;j++)
cout<<i+j<<"s:FIGHT AT ("<<way_node[i].x-<<','<<way_node[i].y-<<')'<<endl;
i += num;
}
}
cout<<"FINISH"<<endl;
}
else{ //没有到达终点
cout<<"God please help our poor hero."<<endl;
cout<<"FINISH"<<endl;
}
}
return ;
}

2014-01-18 16:50:53

  受同学启发,用“优先队列”又写了一遍,顺便学习了一下优先队列的使用。

  思路和上面是基本相同的,只不过遇到怪物时的处理用优先队列简化了许多,优先队列不会用的筒靴可以参考下面的链接:

  优先队列用法

  另外给出一位同样用优先队列实现的博客链接,不过人家是0MS AC,我是31MS AC,有差距啊!

  hdu1026

  下面是我用优先队列做的代码:

 #include <iostream>
#include <string.h>
#include <queue>
using namespace std;
char a[][];
char isv[][]; //记录访问过没有
int dir[][]; //记录每一个节点的来路方向,即整个地图遍历的顺序
int dx[] = {,,,-};
int dy[] = {,,-,};
int N,M;
struct NODE{
int x;
int y;
int step;
friend bool operator < (NODE n1,NODE n2) //自定义优先级。在优先队列中,优先级高的元素先出队列。
{
return n1.step > n2.step; //通过题意可知 step 小的优先级高,需要先出队。
}
};
bool judge(int x,int y)
{
if( x< || y< || x>N || y>M )
return ;
if( isv[x][y] )
return ;
if( a[x][y]=='X' )
return ;
return ;
}
int bfs(int x,int y) //返回从(x,y)开始广搜,到右下角的最短步数,如果无法到达右下角,返回0
{
priority_queue <NODE> q; //定义一个优先队列
NODE cur,next;
cur.x = x;
cur.y = y;
cur.step = ;
q.push(cur); //第一个元素入队
while(!q.empty()){
cur = q.top(); //队首出队,注意不是front()
q.pop();
if(cur.x==N && cur.y==M){ //到终点
return cur.step;
}
for(int i=;i<;i++){
int nx = cur.x + dx[i];
int ny = cur.y + dy[i];
if( judge(nx,ny) ) //判定
continue;
//可以走
next.x = nx;
next.y = ny;
isv[nx][ny] = true;
dir[nx][ny] = i;
if( ''<=a[nx][ny] && a[nx][ny]<='' ){ //这一步有怪物
int hp = a[nx][ny] - '';
next.step = cur.step + hp + ;
}
else //这一步没有怪物
next.step = cur.step + ;
q.push(next);
}
}
return ;
}
int main()
{
while(cin>>N>>M){
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
cin>>a[i][j];
memset(isv,,sizeof(isv));
isv[][] = true;
int step = bfs(,);
if(step){ //step有值,能够到达终点
//还原路径
NODE way[];
int cx=N,cy=M;
for(int i=step;i>=;i--){
way[i].x = cx;
way[i].y = cy;
if(''<=a[cx][cy] && a[cx][cy]<=''){ //当前位置有怪物
int hp = a[cx][cy] - '';
for(int j=;j<=hp;j++){
way[i-j].x = cx;
way[i-j].y = cy;
}
i -= hp;
}
switch(dir[cx][cy]){
case :cy--;break;
case :cx--;break;
case :cy++;break;
case :cx++;break;
default:break;
}
}
//输出结果
cout<<"It takes "<<step<<" seconds to reach the target position, let me show you the way."<<endl;
for(int i = ;i<=step;i++){
cout<<i<<"s:("<<way[i-].x-<<','<<way[i-].y-<<")->("<<way[i].x-<<','<<way[i].y-<<')'<<endl;
if( ''<=a[way[i].x][way[i].y] && a[way[i].x][way[i].y]<='' ){ //如果有怪物
int hp = a[way[i].x][way[i].y] - '';
for(int j=;j<=hp;j++)
cout<<i+j<<"s:FIGHT AT ("<<way[i+j].x-<<','<<way[i+j].y-<<')'<<endl;
i+=hp;
}
}
}
else{ //step为0,说明不能到达终点
cout<<"God please help our poor hero."<<endl;
}
cout<<"FINISH"<<endl;
}
return ;
}

Freecode : www.cnblogs.com/yym2013

hdu 1026:Ignatius and the Princess I(优先队列 + bfs广搜。ps:广搜AC,深搜超时,求助攻!)的更多相关文章

  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】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1026 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  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. jquery获取含有某元素的的控件 “控件名[属性名=值]”

    jquery获取含有某元素的的控件 “控件名[属性名=值]”. 如,获取 <input id="${cheackbox}" data-role="icheck&qu ...

  2. Tomcat 改服务器编码(Java 修改字符串编码格式)

    对于客户端发来的汉字,我们一般需要转码: ------------------------------------------------------------------------------- ...

  3. linux内核——TSS

    task state segment,任务状态段. 关于每个cpu对应不同TSS段的问题,如下解释: TSS段主要用在当前的任务从用户态切入内核态时去找到该任务的内核堆栈. 多核上的任务是真正的并发, ...

  4. Android 弹幕效果开发案例

    概述 现在有个很流行的效果就是弹幕效果,满屏幕的文字从右到左飘来飘去.看的眼花缭乱,看起来还蛮cool的 现在就是来实现这一的一个效果,大部分的都是从右向左移动漂移,本文的效果中也支持从左向右的漂移移 ...

  5. jQuery方法一览

    Attribute: $(”p”).addClass(css中定义的样式类型); 给某个元素添加样式 $(”img”).attr({src:”test.jpg”,alt:”test Image”}); ...

  6. 【LeetCode】117. Populating Next Right Pointers in Each Node II (2 solutions)

    Populating Next Right Pointers in Each Node II Follow up for problem "Populating Next Right Poi ...

  7. sqlserver学习笔记(六)—— sqlserver内置函数(字符串、日期)

    sqlserver中有很多内置函数,这里总结了一些常用的 一.关于字符串的函数: 1.CHARINDEX 寻找一个指定字符串在另一个字符串中的起始位置 SELECT CHARINDEX('world‘ ...

  8. Bootstrap 的模态框类

    事件类型 描述 show.bs.modal show 方法调用之后立即触发该事件.如果是通过点击某个作为触发器的元素,则此元素可以通过事件的relatedTarget 属性进行访问. shown.bs ...

  9. jquery 鼠标拖动排序Li或Table

    1.前端页面 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="拖动排序Li或Ta ...

  10. Python 列表 list() 方法

    描述 Python 列表 list() 方法用于将可迭代对象(字符串.列表.元祖.字典)转换为列表. 注:元组与列表是非常类似的,区别在于元组的元素值不能修改,元组是放在括号中,列表是放于方括号中. ...