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

FZOJ2124吃豆人(bfs+优先队列)

2012年09月26日 ⁄ 综合 ⁄ 共 2402字 ⁄ 字号 评论关闭

->题目请戳这里<-

题目大意:给一个n*m的迷宫,有个人,位置是p,有个豆子,位置是b,可能有一个宝贝,位置在s,其他的要么是障碍X,要么是空地.,现在人要吃豆子,人只能上下左右移动,每次花时间1秒,这个人的舌头比较长,如果他和豆子之间没有障碍,他直接伸舌头就能把豆子吃了,舌头走一格只要0.1秒(舌头要收回来才能吃豆子)。宝贝是用来加速的,吃了宝贝后人的移动速度就快了一倍,即走一格只要0.5秒。现在要求最小吃豆时间,如果吃不了豆输出-1。

题目分析:BFS做。这题烦人烦在那个宝贝,由于最多一个宝贝,所以我们分2种情况:

1,直接去吃豆子,算出最短时间。

2,先去找宝贝,再去找豆子。

答案就是两者最小值。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
char map[25][25];//地图
bool mark[25][25];//标记
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
int si,sj,ei,ej,pi,pj;
int flag;
int n,m;
struct node
{
    int x,y;
    double time;
    bool flag;//是否获得加速
    friend bool operator< (struct node a,struct node b)
    {
        return a.time > b.time;
    }
}s,now;
priority_queue<node> lcm;

int find()//bfs找宝贝
{
    int i;
    if(flag == 0)
        return -1;
    while(!lcm.empty())
        lcm.pop();
    s.x = si;
    s.y = sj;
    s.time = 0;
    lcm.push(s);
    memset(mark,0,sizeof(mark));
    while(!lcm.empty())
    {
        now = lcm.top();
        lcm.pop();
        for(i = 0;i < 4;i ++)
        {
            s = now;
            s.x += dx[i];
            s.y += dy[i];
            if(s.x < 1 || s.y < 1 || s.x > n || s.y > m || mark[s.x][s.y] || map[s.x][s.y] == 'X')
                continue;
            s.time ++;
            if(map[s.x][s.y] == 'S')
                return s.time;
            lcm.push(s);
            mark[s.x][s.y] = 1;
        }
    }
    return -1;
}

int isok()//直接伸舌头一定是最快的
{
    int i;
    if(s.x == ei)
    {
        for(i = min(s.y,ej) + 1;i < max(s.y,ej);i ++)
            if(map[ei][i] == 'X')
                break;
        if(i == max(s.y,ej))
        {
            s.time += 0.2 * abs(s.y - ej);
            return 1;
        }
        return 0;
    }
    if(s.y == ej)
    {
        for(i = min(s.x,ei) + 1;i < max(s.x,ei);i ++)
            if(map[i][ej] == 'X')
                break;
        if(i == max(s.x,ei))
        {
            s.time += 0.2 * abs(s.x - ei);
            return 1;
        }
        return 0;
    }
    return 0;
}

double Bfs(int a,int b,int c)
{
    int i;
    while(!lcm.empty())
        lcm.pop();
    s.x = a;
    s.y = b;
    s.flag = c;
    s.time = 0;
    memset(mark,0,sizeof(mark));
    if(isok())
    {
        //printf("%.1lf\n",s.time);
        return s.time;
    }
    lcm.push(s);
    mark[s.x][s.y] = 1;
    while(!lcm.empty())
    {
        now = lcm.top();
        lcm.pop();
       // printf("%d %d\n",now.x,now.y);
        for(i = 0;i < 4;i ++)
        {
            s = now;
            s.x += dx[i];
            s.y += dy[i];
            if(s.flag)
                s.time += 0.5;
            else
                s.time += 1;
            if(s.x < 1 || s.y < 1 || s.x > n || s.y > m || mark[s.x][s.y] || map[s.x][s.y] == 'X')
                continue;
            if(isok())
            {
                //printf("%.1lf\n",s.time);
                return s.time;
            }
            if(map[s.x][s.y] == 'S')
                s.flag = 1;
            lcm.push(s);
            mark[s.x][s.y] = 1;
        }
    }
    return -1;
}

int main()
{
    int i,j;
    while(~scanf("%d%d",&n,&m))
    {
        flag = 0;
        getchar();
        for(i = 1;i <= n;i ++)
        {
            for(j = 1;j <= m;j ++)
            {
                map[i][j] = getchar();
                if(map[i][j] == 'P')
                {
                    si = i;
                    sj = j;
                }
                if(map[i][j] == 'B')
                {
                    ei = i;
                    ej = j;
                }
                if(map[i][j] == 'S')
                {
                    flag = 1;
                    pi = i;
                    pj = j;
                }
            }
            getchar();
        }
        double ans = Bfs(si,sj,0);//直接找
        int tmp = find();
        if(tmp != -1)
        {
            double tp = Bfs(pi,pj,1);
            if(tmp + tp < ans)
                ans = tmp + tp;
        }
        printf("%.1lf\n",ans);
    }
    return 0;
}
/*
6 5
.S...
PXXX.
.XXX.
.XB..
.X.X.
.....
6 5
S....
PXXX.
.XXX.
.X...
.X.X.
..B..
3 3
...
PXB
XXX
3 3
P..
..B
XXX
3 3
S..
PXB
XXX
2 2
XP
B.
3 2
XP
.S
B.
4 3
SPX
..X
..X
..B
*/

抱歉!评论已关闭.