Fzu2124 - 吃豆人 BFS

Description

吃豆人是一款非常经典的游戏,游戏中玩家控制吃豆人在地图上吃光所有豆子,并且避免被怪物抓住。

这道题没有怪物,将游戏的画面分成n*m的格子,每格地形可能为空地或者障碍物,吃豆人可以在空地上移动,吃豆人每移动一格需要1s时间,并且只能朝上下左右四个方向移动,特别的是吃豆人还能吐出舌头,舌头每移动一格需要0.1s时间,舌头只可以走直线。不必考虑吃豆人转身所需要的时间。

举例,吃豆人在(1,1)坐标,而豆子在(1,5)坐标,并且中间没有障碍物,此时朝豆子方向吐舌头~,经过0.8s就可以吃到豆子(来回各0.4s,吐出去的舌头要缩回来的嘛)。

游戏中还有加速道具,一旦得到加速道具,吃豆人就获得2倍移动速度,吐舌头的速度没有增加,即走1格用0.5s。现在地图上有且只有一颗豆子。游戏中有.代表空地;X表示障碍,吃豆人不能越过障碍;B代表豆子;S代表加速道具,并且地图上道具总数不超过1个,道具所在的位置为空地,得到道具后立即使用,道具立即消失,地形变为空地,不能用舌头去取道具;P表示吃豆人,吐舌头的时候吃豆人不能移动。

Input

输入包含多组数据。输入第一行有两个个整数n,m(2<=n,m<=20),接着一个n*m的地图矩阵。

对于50%的数据,地图上没有道具。

Output

输出一行,最快用多少s吃到豆子,结果保留1位小数,如果吃不到,输出-1。

Sample Input

2 2

XP

B.

3 2

XP .

S B.

Sample Output

1.2

1.7

思路:舌头是不能越过障碍的。由于道具最多只有一个,我们分两种情况,一是不拿道具,那么可先BFS出起点到各个点的最短距离,然后再枚举每个可以走到的位置,判断在该位置吐舌头能否得到更优解。二是从起点去拿道具,然后从道具那个位置出发,也BFS出道具到每个点的最短距离,考虑到达每个位置吐舌头能否得到更优解

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
int n, m;
char mat[25][25];

int px, py, bx, by, sx, sy;

struct node {
    int x, y;
    node() {}
    node(int x, int y) : x(x), y(y) {}
};
queue<node> que;
int dir[][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
int md[2][25][25], vis[25][25];
void init() {
    memset(md, INF, sizeof md);
    sx = sy = -1;
    for(int i = 0; i < n; ++i)
    for(int j = 0; j < m; ++j) {
        if(mat[i][j] == ‘P‘) px = i, py = j;
        if(mat[i][j] == ‘B‘) bx = i, by = j;
        if(mat[i][j] == ‘S‘) sx = i, sy = j;
    }
}
bool check(int x, int y) {
    if(x < 0 || x >= n || y < 0 || y >= m || vis[x][y] || mat[x][y] == ‘X‘) return false;
    return true;
}
void BFS(int x, int y, int f) {
    while(!que.empty()) que.pop();
    memset(vis, 0, sizeof vis);
    vis[x][y] = 1;
    que.push(node(x, y));
    md[f][x][y] = 0;
    node u, v;
    while(!que.empty()) {
        u = que.front();
        que.pop();
        for(int i = 0; i < 4; ++i)
        {
            v.x = u.x + dir[i][0];
            v.y = u.y + dir[i][1];
            if(check(v.x, v.y)) {
                que.push(v);
                vis[v.x][v.y] = 1;
                md[f][v.x][v.y] = md[f][u.x][u.y] + 1;
            }
        }
    }
}
double ans;

int to(int x, int y) {
    if(bx == x) {
        int y1 = min(by, y), y2 = max(by, y);
        for(int i = y1 + 1; i <= y2; ++i) if(mat[x][i] == ‘X‘) return -1;
        return y2 - y1;
    }else if(by == y) {
        int x1 = min(bx, x), x2 = max(bx, x);
        for(int i = x1 + 1; i <= x2; ++i) if(mat[i][y] == ‘X‘) return -1;
        return x2 - x1;
    }
    return -1;
}
void solve1() {
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) if(md[0][i][j] != INF) {
            int dis = to(i, j);
            if(dis == -1) continue;
            ans = min(ans, md[0][i][j] + (double)dis * 0.1 * 2);
        }
    }
}
void solve2() {
    int res = md[0][sx][sy];
    if(res == INF) return;
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) if(md[1][i][j] != INF) {
            int dis = to(i, j);
            ans = min(ans, res + md[1][bx][by] / 2.0);
            if(dis != -1) ans = min(ans, res + md[1][i][j] / 2.0 + (double)dis * 0.1 * 2);
        }
    }
}
int main() {
    //freopen("in", "r", stdin);
    while(~scanf("%d%d", &n, &m)) {
        for(int i = 0; i < n; ++i) scanf("%s", mat[i]);
        init();
        BFS(px, py, 0);
        if(sx != -1)
        BFS(sx, sy, 1);

        ans = INF;
        if(md[0][bx][by] == INF) { puts("-1"); continue; }
        solve1();
        if(sx != -1)
        solve2();
        printf("%.1f\n", ans);
    }
    return 0;
}

时间: 2024-11-05 10:43:20

Fzu2124 - 吃豆人 BFS的相关文章

TurnipBit开发板DIY呼吸的吃豆人教程实例

转载请以链接形式注明文章来源(MicroPythonQQ技术交流群:157816561,公众号:MicroPython玩家汇) 0x00前言 吃豆人是耳熟能详的可爱形象,如今我们的TurnipBit也集成了这可爱的图形,我们这就让他来呼吸了~. 0x01效果展示 先一起看下最终的成品演示视频: 0x02准备 TurnipBit一块 数据线一条 TurnipBit可视化编程网站:www.tpyboard.com 0x03代码实现 打开我们的TurnipBit在线图形编辑器. http://www.

css吃豆人动画

一. Css吃豆人动画 1. 上半圆:两个div,内部一个圆div,外部设置宽高截取半圆 外部div动画:animation: 动画样式 1s(时长) ease(动画先低速后快速) infinite(动画无限播放) 动画样式:@keyframes:设置50%转45度,100%转0度 transform-origin: 50% 100%:定义旋转基点位置,左上角为0% 0% 2. 下半圆:改变旋转动画和基点位置,截取下半圆令外部div向下移动50%:translateY(-50%) 3. 豆子(设

做吃豆人所学知识

a.playerSelect设置分辨率. b.可以改图片的每个像素单位. c.碰撞体编辑可以按alt同步. d.雪碧图mode改成多张. e.平面切图前后都要apply. d按ctrl整数拖动. f.浮点数不精确切记0.01 g.可以通过设置不让自己转换到自己 h.2d动画去掉融合. j.start的时候目的地设置为自身. k.通过rigidbody改变移动最好. l.moveTowards  和lerp的区别做差值. l. Vector2 temp = Vector2.MoveTowards 

Pac-Man 吃豆人

发售年份 1980 平台 街机 开发商 南梦宫(Namco) 类型 迷宫 https://www.youtube.com/watch?v=dScq4P5gn4A 原文地址:https://www.cnblogs.com/revoid/p/10546571.html

【猿团专访】|村支书的创业梦:让吃的人健康,让养的人小康

他曾是年薪18万副总,缘何放弃高薪工作回到偏远老家? 23岁村支书,靠什么在一片质疑声中,赢得乡亲们的拥戴爱护? 中国村支书数不胜数,为何CCTV要对他的事迹进行报道? 堂堂七尺男儿,又是什么让他几度失控落泪? 本期猿团专访,走近广元市苍溪县白驿镇岫云村村支书李君,了解这个村支书的创业梦. 本期嘉宾: 李君, 广元市苍溪县白驿镇岫云村村党支部书记,31岁,在任支部书记8年期间先后获得苍溪县十大杰出青年,广元市优秀基层党组织书记,共青团四川省第十三届委员,四川省优秀基层党组织书记,四川省五四青年奖

[Jobdu] 题目1408:吃豆机器人

题目描述: 淘宝公司内部有许多新鲜的小玩具,例如淘宝智能机器人.小时候,大家都玩过那个吃豆子的游戏吧,这机器人就是按照这个游戏设计的,它会朝着豆子的方向行走.不过机器人还存在一个bug,他只会朝南和朝东走.现在有一块空地,分成了n*m个格子,每个格子内有一颗豆子.机器人的起点在西北角,终点在东南角.请问机器人从起点到终点有多少种不同的方法. 输入: 每个案例输入只有一行,有n和m两个正整数,n,m均小于等于10^3.由于答案很大,所以答案对10009取余. 输出: 对于每个案例,输出一行,输出机

BZOJ 1930 SHOI 2003 pacman 吃豆豆 费用流

题目大意:给出一些平面上的点,你有两个吃豆人,从一个点出发,这个吃豆人可以吃到当前点右上方的点.问这两个吃豆人最多可以吃到多少豆子. 思路:我已經吧不相交的条件去掉了.. 不加优化的费用流模型很明显 超级源->源 flow2 cost0 汇->超级汇 flow2 cost0 下面是拆点 i << 1 -> i << 1|1 flow1 cost1 对于从点i能够到达点j的情况 i << 1|1 - > j << 1 flow1 cos

[LeetCode] Dungeon Game

The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his wa

(转) 网络游戏实时动作同步方案手记

和MMORPG不同,实时动作型网络游戏 追求操作的响应要求极高(<150ms).动作型网络游戏的制作人希望做到单机游戏的体验,网络游戏的服务.    网络指令在多客户端间的同步算法,从原理上来说,围绕两种特性的取舍而定:  * 牺牲局部实时性:某程度的互等待,保证各客户端间指令集在指定时间段一致.  * 牺牲局部一致性:容许客户端本机先行模拟,等待后续指令到达纠正.(DR) 网络的存在导致鱼与熊掌不可兼得,所以现在市面上的动作网络游戏都有如下的妥协和折衷实现:  * 在客户端本机上算大量关键运算