您的位置:首页 > 其它

HDU 1242 bfs

2017-08-24 00:00 197 查看
因为如果用普通方法,最后得到的是最优步数,而不是最优时间;

来自Jason的解释:

普通队列+bfs确实是蒙对的,因为击败守卫需要消耗时间1
,因此普通队列每一次出队列的元素只是步数上最优,
但不一定是时间上最优的,这时即使我们把整个迷宫搜完以最小值作为最优依然不行,
因为每一步处理完成都会把该状态标记为已处理vis[i][j]=1,
因此,只要有一步不是最优,就会影响后面的结果。
这题的正确做法是优先队列,每一次出队都是出时间最少的,
这样可以保证每一步最优,并且一旦搜到目标即可立刻结束。


题意:天使被困在监狱,他的朋友们想见他,监狱的地形复杂,包括路(用点标示),墙(用#标示),天使的位置(用a标示),他的朋友(用r标示),监狱里还有守卫(用x标示),他的朋友只能向左右上下四个方向走,走以不花一单位时间,若碰上守卫,消灭守卫需要额外花费一单位时间。问最少多长时间天使能见到他的朋友。

本题需要注意的是,天使的朋友可能不只一个,所以,应该从天使的位置开始搜去找其朋友就ok了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>

#define LL long long
int const MAX = 1e6 + 1;
int const INF = 1 << 30;
double const EPS = 0.00000001;
using namespace std;

char g[202][202];
bool vis[202][202];
int n, m, ans;
struct Node {
int x, y, step;
Node(int x = 0, int y = 0, int step = 0) : x(x), y(y), step(step){}
};

bool operator < (Node n1, Node n2){
return n1.step > n2.step;
}

Node st, tnd;

int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int main(){
while (scanf("%d%d", &n, &m) == 2){
for (int i = 0; i < n; i++){
scanf("%s", g[i]);
for (int j = 0; j < m; j++)
if (g[i][j] == 'a')
st.x = i, st.y = j, st.step = 0;
}

memset(vis, 0, sizeof(vis));
priority_queue<Node> q;
q.push(st);
vis[st.x][st.y] = 1;
ans = -1;
while (!q.empty()){
Node nd = q.top();
q.pop();

if (g[nd.x][nd.y] == 'r'){
ans = nd.step;
break;
}
for (int k = 0; k < 4; k++){
int nx = nd.x + dir[k][0], ny = nd.y + dir[k][1], ns = nd.step + 1;
if (nx < 0 || ny < 0 || nx >= n || ny >= m
|| vis[nx][ny] || g[nx][ny] == '#')
continue;
if (g[nx][ny] == 'x') ns++;
vis[nx][ny] = 1;
q.push(Node(nx, ny, ns));
}
}

if (ans == -1)
printf("Poor ANGEL has to stay in the prison all his life.\n");
else
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  优先队列 bfs