题意:在一个N*M的矩阵里面,有一个吃豆人,每次可以上下左右移动,每次移动消耗1s,有些格子有障碍,矩阵中有且仅有一个豆子,吃豆人沿直线可以吐舌头吃豆,舌头伸长一格消耗0.1s,吃完还要收缩回来,收缩一个也消耗0.1s。地图中至多有一个加速器,吃了加速器以后速度变成原来的两倍,吐舌头速度不变。问到豆子至少要多久,如果吃不到输出-1。
思路:1.先考虑没有加速器的情况,因为只有一个豆子,因此可以以豆子为中心,往四个方向初始化出各个格子要吃豆子时消耗的时间。因为只要走到可吃豆的点时,走路永远没有吐舌头快(走一格1s,有加速器0.5s,而吐舌头一格来回才0.2s),所以我们只要用BFS寻找到达这些可以吃豆的点中,吃豆加移动总时间最少的解。
2.如果有加速器,那我们先算出没有加速器时的最优解,记为ans1。然后考虑吃先吃加速器的最短耗时,再计算由加速器走到可吃豆点并吃豆的最短耗时,两者加起来记为ans2,答案输出ans=min(ans1,ans2)即可。
3.可以将ans值一开始记为INF,如果求出来ans为INF,则输出-1。
就是实现起来稍微麻烦。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
char map[25][25];
bool vis[25][25],Dj;
double dist[25][25],ans,fast,pre;
int n,m,Bx,By,Sx,Sy,Djx,Djy,dx[]={0,0,1,-1},dy[]={1,-1,0,0};
void prework()//初始化每个可吃豆点吐舌头吃豆来回需要的时间
{
for(int i=0;i<n;++i)
for(int j=0;j<m;++j) dist[i][j]=INF;//初始化所有点都不可吃豆
for(int i=0;i<4;++i)
for(int x=Bx,y=By,cnt=0;x<n && y<n && x>=0 && y>=0 && map[x][y]!='X';x+=dx[i],y+=dy[i]) dist[x][y]=(cnt++)*0.2;
}
struct point{int x, y;double tim;};
bool check(point t)
{
if(t.x<0 || t.y<0 || t.x>=n || t.y>=m || vis[t.x][t.y] || map[t.x][t.y]=='X') return 0;
return 1;
}
void bfs1(point qidian)
{
memset(vis,0,sizeof(vis));
queue<point> Q;
Q.push(qidian);
while(!Q.empty())
{
point top=Q.front(); Q.pop();vis[top.x][top.y]=1;
if(dist[top.x][top.y]<INF) ans=min(ans,top.tim+dist[top.x][top.y]);
for(int i=0;i<4;++i)
{
point tmp={top.x+dx[i],top.y+dy[i],top.tim+fast};
if(check(tmp))
if(dist[tmp.x][tmp.y]<INF) ans=min(ans,tmp.tim+dist[tmp.x][tmp.y]);
else {Q.push(tmp);vis[tmp.x][tmp.y]=1;}
}
}
}
void bfs2(point qidian)
{
memset(vis,0,sizeof(vis));
queue<point> Q;
Q.push(qidian);
pre=0.0;
while(!Q.empty())
{
point top=Q.front(); Q.pop();vis[top.x][top.y]=1;
for(int i=0;i<4;++i)
{
point tmp={top.x+dx[i],top.y+dy[i],top.tim+1.0};
if(check(tmp))
if(map[tmp.x][tmp.y]=='S') {pre=tmp.tim;return;}
else {Q.push(tmp);vis[tmp.x][tmp.y]=1;}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
getchar();
for(int i=0;i<n;++i) scanf("%s",map[i]);
Dj=0,ans=INF,fast=1.0;
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
if(map[i][j]=='B') {Bx=i,By=j;}
else if(map[i][j]=='P') {Sx=i,Sy=j;}
else if(map[i][j]=='S') {Dj=1,Djx=i,Djy=j;}
prework();
point qd={Sx,Sy,0.0};
if(Dj==0) bfs1(qd);
else
{
bfs1(qd);
bfs2(qd);
point nqd={Djx,Djy,pre};
fast=0.5;
bfs1(nqd);
}
if(ans>=INF-5) printf("-1\n");
else printf("%.1lf\n",ans);
}
}