Name:Ignatius and the Princess I
P_ID:HDU 1026
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1026
题意描述:
就是普通迷宫加上一些权重。另外要输出路径。
题目分析:
本题的难点在于路径的输出。为了达到按序输出路径,本题除了要使用优先队列求得bfs最短路之外,还要用栈stack来输出路径。
本题的输出采用栈结构,这是一种输出路径的经典做法。要好好揣摩。
注意到本题采用的是优先队列,而不是普通队列。在路径存在权重的时候,就不能用普通队列了,就需要用优先队列。
思路附在代码注释中:
参考代码:
/**
* method2: priority_queue最短路 + stack输出
* P_ID: HDU 1026
* date: 2016-04-22
* level: dificult
*/
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
int N, M;
struct cell {
int x;
int y;
int time;
//重载小于号,使之满足priority_queue的排序要求
friend bool operator < (const cell& a, const cell &b)
{
return a.time > b.time;
}
}path[105][105];
char maze[105][105];
int vis[105][105];
const int dir[][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}};
int ansTime;
bool check(int x, int y)
{
if(x<0 || y<0 || x>=N || y>=M) return false;
if(maze[x][y]=='X') return false;
return true;
}
int bfs(cell s)
{
priority_queue<cell> myCell;
myCell.push(s);
vis[0][0] = 1;
while (!myCell.empty())
{
cell head = myCell.top();
myCell.pop();
//终止条件,第一次到这里一定是最短路径
if(head.x==N-1 && head.y==M-1)
return head.time;
for(int i=0; i<4; ++i)
{
int xx = head.x + dir[i][0];
int yy = head.y + dir[i][1];
if(check(xx, yy) && !vis[xx][yy])
{
vis[xx][yy] = 1;
//以下三行,用来存储路径,注意这里不是用想当然的字符串string也不是用一个vector不断的push进去(会浪费大量空间,同时极不方便后续输出),而是采用一个与迷宫一样大的二维数组,每个grid内存的是其父grid,也就是来路
path[xx][yy].x = head.x;
path[xx][yy].y = head.y;
path[xx][yy].time = head.time + 1;
//下一步
cell next;
next.x = xx;
next.y = yy;
next.time = head.time + 1;//注意,就算是怪兽,也有一个移动到这里的时间1,相当于打怪兽花的时间是另外加上算的
if(maze[xx][yy]=='.') myCell.push(next);
else
{
//maze是char类型,要进行转换
next.time = next.time + maze[xx][yy] - '0';
myCell.push(next);
}
}
}
}
return -1;//到不了终点了,营救失败
}
void print()
{
if(ansTime==-1) printf("God please help our poor hero.\n");
else
{
printf("It takes %d seconds to reach the target position, let me show you the way.\n", ansTime);
stack<cell> st;
cell t = path[N-1][M-1];
//终点位置需要单独最先入栈,因为没有任何位置存的父节点是最终位置
cell rMin;
rMin.x = N-1;
rMin.y = M-1;
rMin.time = ansTime;
st.push(rMin);
while (t.x||t.y)//只有当t.x==t.y==0才为假
{
st.push(t);
t = path[t.x][t.y];
}
int k=1;
while (!st.empty())
{
t = st.top();
st.pop();
printf("%ds:(%d,%d)->(%d,%d)\n", k++, path[t.x][t.y].x, path[t.x][t.y].y, t.x, t.y);
if(maze[t.x][t.y]!='.')
{
int tmp = maze[t.x][t.y] - '0';
while(tmp--)
{
printf("%ds:FIGHT AT (%d,%d)\n", k++, t.x, t.y);
}
}
}
}
printf("FINISH\n");
return;
}
int main()
{
while (~scanf("%d%d", &N, &M))
{
ansTime = 999999;
memset(maze, 0, sizeof(maze));
memset(vis, 0, sizeof(vis));
for(int i=0; i<N; ++i)
scanf("%s", maze[i]);
cell start;
start.x = 0;
start.y = 0;
start.time = 0;
ansTime = bfs(start);
print();
}
return 0;
}