您的位置:首页 > 其它

HDU1026——Ignatius and the Princess I

2016-08-16 18:09 465 查看
先看题目。

Problem Description

The Princess has been abducted by theBEelzebub feng5166, our hero Ignatius has to rescue our pretty Princess. Now hegets into feng5166's castle. The castle is a large labyrinth. To make theproblem simply, we assume the labyrinth is a N*M two-dimensional
array whichleft-top corner is (0,0) and right-bottom corner is (N-1,M-1). Ignatius entersat (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 killthem. Here is
some rules:

1.Ignatius can only move in four directions(up, down, left, right), one stepper second. A step is defined as follow: if current position is (x,y), after astep, 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 likethis:

. : 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, ittakes him n seconds to kill the monster.

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

 

Input

The input contains several test cases. Eachtest case starts with a line contains two numbers N andM(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 targetposition, or you should output "It takes n seconds to reach the targetposition, let me show you the way."(n is the minimum seconds), and tellour hero
the whole path. Output a line contains "FINISH" after eachtest case. If there are more than one path, any one is OK in this problem. Moredetails 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 targetposition, let me show you th
4000
e 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 targetposition, 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

 

 

读完这题第一反应是DFS,但是题目里还要求输出路径啊,再加个记忆化可能是个不错的选择。

转念一想曾经做过一道类似的题目,7*7的小地图用DFS都差点爆掉,这次100*100可不是闹着玩的,那就只能用BFS了。但是打怪兽是需要时间的,而普通BFS的队列又是先进先出,可能怪兽还没打完这个点就出队了……所以最后想到了用优先队列代替普通队列。这样每次出队的都是优先级最高的,再确定时间短作为优先队列的高优先级处理即可。

由于没做过优先队列,所以借鉴了某位同学的优先队列讲解示例代码(已经修改后加入模板库)。

感谢http://www.cnblogs.com/heqinghui/archive/2013/07/30/3225407.html

接下来是代码。

//冗余代码太多了,没来得及改,望理解
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;

//由于优先级队列默认是优先级对应值较大的先出,所以根据题意重载优先级比较符
typedef struct p{
int x,y,t;
bool operator < (const p &a)const
{
return t>a.t;//取时间最少优先
}
}Point;

int n,m;
char nm[110][110];
char backup[110][110];      //备用数组,稍后统计打怪兽用时时用
int flag[110][110];     //标记行走方向
int  dir[][2]={{0,0},{1,0},{-1,0},{0,1},{0,-1}};        //方向数组
int dirr[][2]={{0,0},{-1,0},{1,0},{0,-1},{0,1}};        //反方向数组(direction_reversed)
Point start;

int bfs(){
priority_queue<Point>que;
Point cur, next;
//对开始点的处理
nm[0][0]='X';
que.push(start);
//开始优先队列bfs
//把方向存在当前节点上时容易被覆盖导致错误答案(当不合理的转向出现在合理转向之后时)
while(!que.empty()){
cur = que.top();
que.pop();
for(int i=1; i<5; i++){
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
next.t=cur.t+1;
if(next.x<0 || next.y<0 || next.x>=n || next.y>=m)
continue;
if(nm[next.x][next.y]=='X'){
continue;
}
if(next.x==n-1 && next.y==m-1){
flag[next.x][next.y]=i;
return next.t;
}
if(nm[next.x][next.y]=='.'){
nm[next.x][next.y]='X';
flag[next.x][next.y]=i;
que.push(next);
}
else {
int cnt = nm[next.x][next.y]-'0';
nm[next.x][next.y]='X';
next.t+=cnt;
flag[next.x][next.y]=i;
que.push(next);
}
}
}
return -1;
}

//读程序请从这里开始
int main(){
start.t=0,start.x=0,start.y=0;      //起点的数据
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
flag[i][j]=0;
}
}
//读入并复制一个备份,这样读入的数据就可以随意修改了
for(int i=0; i<n; i++){
scanf("%s",nm[i]);
strcpy(backup[i],nm[i]);
}
//调用bfs
int result = bfs();
//如果走不到终点
if(result == -1){
printf("God please help our poor hero.\nFINISH\n");
continue;
}
else{       //如果能走到终点
//刚才我们提过当前节点的方向其实是存在了下一个节点里
//因此我们现在将这些节点的方向调整到正常的位置上以便从入口开始
int ex=n-1,ey=m-1, current=0,last=0;
for(int i=0; i<result; i++){
//先把上一个位置用反向数组算出来
int tex=ex, tey=ey;
tex+=dirr[flag[ex][ey]][0], tey+=dirr[flag[ex][ey]][1];
//针对每种方向的转存方案(写的太冗长了2333)
switch(flag[ex][ey]){
case(0):{
flag[ex][ey]=current;
break;
}
case(1):{
last=1;
flag[ex][ey]=current;
current=last;
break;
}
case(2):{
last=2;
flag[ex][ey]=current;
current=last;
break;
}
case(3):{
last=3;
flag[ex][ey]=current;
current=last;
break;
}
case(4):{
last=4;
flag[ex][ey]=current;
current=last;
break;
}
}
//别忘了更新位置
ex=tex;ey=tey;
}
//专门针对最后一步有怪兽的情况
if(backup[n-1][m-1]!='.')result+=backup[n-1][m-1]-'0';
//开始从入口依次输出答案
printf("It takes %d seconds to reach the target position, let me show you the way.\n",result);
int x=0,y=0;
for(int i=0; i<result; i++){
printf("%ds:(%d,%d)->(%d,%d)\n",i+1,x, y, x+dir[flag[x][y]][0], y+dir[flag[x][y]][1]);
int tx=x;
x+=dir[flag[x][y]][0], y+=dir[flag[tx][y]][1];
if(backup[x][y]<='9' && backup[x][y]>'0'){
for(char j=0; j<backup[x][y]-'0'; j++){
i++;
printf("%ds:FIGHT AT (%d,%d)\n",i+1,x,y);
}
}
}
//千万别忽略了题目要求输出的小尾巴
printf("FINISH\n");
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  优先队列 BFS