现在的位置: 首页 > 综合 > 正文

FZU 2124 吃豆人 (BFS)

2018年02月23日 ⁄ 综合 ⁄ 共 2620字 ⁄ 字号 评论关闭

题意:在一个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);
    }
}

抱歉!评论已关闭.