题目链接:http://hihocoder.com/problemset/problem/1828
题意是问有一个人从S点走到T点的最短路程,其中有氧气瓶分布在地图中,用'B'表示,它的作用是可以穿过'#'毒气室,每次穿过一个毒气室消耗一个氧气瓶,而氧气瓶最多能带5个,还有就是穿过毒气室需要额外花费1s的时间,地图中还存在加速药丸,用'P'表示,可以有无限个,每使用一次可以节省1s的时间。
思路就是优先队列的bfs去跑,对于那些条件表示清楚就可以了。直接看代码吧,不难理解。
AC代码:
#include <bits/stdc++.h>
#define maxn 105
using namespace std;
struct Node{
int x,y,num,step;
Node (int x,int y,int num,int step) : x(x), y(y), num(num), step(step) {}
bool operator < (const Node &a) const {
if(a.step == step)return a.num < num;
return a.step < step;
}
};
int n,m,_Sx,_Sy,_Ex,_Ey;
int dir[4][2] = {1,0,0,1,-1,0,0,-1};
bool vis[maxn][maxn][10];
char MAP[maxn][maxn];
bool Check(int x, int y){
if(x >= 0 && y >= 0 && x < n && y < m){
return true;
}
return false;
}
int bfs(){
priority_queue<Node> q;
memset(vis,0,sizeof(vis));
vis[_Sx][_Sy][0] = 1;
q.push(Node(_Sx, _Sy, 0, 0));
while(!q.empty()){
Node Now = q.top();
q.pop();
if(Now.x == _Ex && Now.y == _Ey){
return Now.step;
}
for(int i=0;i<4;i++){
int xx = Now.x + dir[i][0];
int yy = Now.y + dir[i][1];
int num = Now.num;
int step = Now.step;
if(Check(xx, yy)){
if((MAP[xx][yy] == '.' || MAP[xx][yy] == 'S' || MAP[xx][yy] == 'T') && !vis[xx][yy][num]){
vis[xx][yy][num] = 1;
q.push(Node(xx, yy, num, Now.step + 1));
}
if(MAP[xx][yy] == 'B' && num < 5 && !vis[xx][yy][num + 1]){
vis[xx][yy][num + 1] = 1;
q.push(Node(xx, yy, num + 1, Now.step + 1));
}
if(MAP[xx][yy] == 'P' && !vis[xx][yy][num]){
vis[xx][yy][num] = 1;
q.push(Node(xx, yy, num, Now.step));
}
if(MAP[xx][yy] == '#' && num > 0 && !vis[xx][yy][num - 1]){
vis[xx][yy][num - 1] = 1;
q.push(Node(xx, yy, num - 1, Now.step + 2));
}
}
}
}
return -1;
}
int main()
{
while(~scanf("%d%d",&n,&m)){
if(n == 0 && m == 0)break;
for(int i=0;i<n;i++){
scanf("%s",MAP[i]);
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(MAP[i][j] == 'S'){
_Sx = i;
_Sy = j;
}
else if(MAP[i][j] == 'T'){
_Ex = i;
_Ey = j;
}
}
}
int ans = bfs();
printf("%d\n",ans);
}
return 0;
}