zoukankan      html  css  js  c++  java
  • AcWing 2548. 大胖子走迷宫(BFS)

    小明是个大胖子,或者说是个大大胖子,如果说正常人占用 1×1 的面积,小明要占用 5×5 的面积。

    由于小明太胖了,所以他行动起来很不方便。

    当玩一些游戏时,小明相比小伙伴就吃亏很多。

    小明的朋友们制定了一个计划,帮助小明减肥。

    计划的主要内容是带小明玩一些游戏,让小明在游戏中运动消耗脂肪。

    走迷宫是计划中的重要环节。

    朋友们设计了一个迷宫,迷宫可以看成是一个由 n×n 个方阵组成的方阵,正常人每次占用方阵中 1×1 的区域,而小明要占用 5×5 的区域。

    小明的位置定义为小明最正中的一个方格。

    迷宫四周都有障碍物。

    为了方便小明,朋友们把迷宫的起点设置在了第 3 行第 3 列,终点设置在了第 n−2 行第 n−2 列。

    小明在时刻 0 出发,每单位时间可以向当前位置的上、下、左、右移动单位 1 的距离,也可以停留在原地不动。

    小明走迷宫走得很辛苦,如果他在迷宫里面待的时间很长,则由于消耗了很多脂肪,他会在时刻 k 变成一个胖子,只占用 3×3 的区域。

    如果待的时间更长,他会在时刻 2k 变成一个正常人,只占用 1×1 的区域。

    注意,当小明变瘦时迷宫的起点和终点不变。

    请问,小明最少多长时间能走到迷宫的终点。

    注意,小明走到终点时可能变瘦了也可能没有变瘦。

    输入格式

    输入的第一行包含两个整数 n,k。

    接下来 n 行,每行一个由 n 个字符组成的字符串,字符为 + 表示为空地,字符为 * 表示为阻碍物。

    输出格式

    输出一个整数,表示答案。

    数据范围

    1≤n≤300,
    1≤k≤1000

    输入样例:

    9 5
    +++++++++
    +++++++++
    +++++++++
    +++++++++
    +++++++++
    ***+*****
    +++++++++
    +++++++++
    +++++++++
    

    输出样例:

    16
    

    bfs即可。注意:可以原地站着等到体积变小后再走,但只要体积变为1的话就只能走了。开一个vis数组标记走过的地方(因为绕了一圈绕回去不如在原地停留更优),以及必须用变之前的体积去判断能否往下走而非用走过去变化后的体积判断。

    #include <iostream>
    #include <queue>
    #include <cstring>
    using namespace std;
    int n, k;
    char mp[305][305];
    int ans = 0x3f3f3f3f;
    int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    bool vis[305][305] = {0};
    //之前不能通过的地方 过一段时间后没准就能过去了 所以vis数组..
    struct node
    {
        int x, y, size, t;
    };
    bool judge(int x, int y, int size)
    {
        for (int i = x - size / 2; i <= x + size / 2; i++)
        {
            for (int j = y - size / 2; j <= y + size / 2; j++)
            {
                if(i < 1 || i > n || j < 1 || j > n || mp[i][j] != '+')
                    return 0;
            }
        }
        return 1;
    }    
    queue<node> q;
    void bfs()
    {
        memset(vis, 0, sizeof(vis));
        node start = {3, 3, 5, 0};
        q.push(start);
        int cnt = 0;
        while(q.size())
        {
            cnt++;
            node now = q.front();
            q.pop();
            vis[now.x][now.y] = 1;
            if (now.x == n - 2 && now.y == n - 2)
            {
                ans = now.t;
                break;
            }
            if (now.t < k) now.size = 5;
            else if(now.t >= k && now.t < 2 * k) now.size = 3;
            else now.size = 1;       
            if (now.size != 1)
            {
                node tmp = {now.x, now.y, now.size, now.t + 1};
                q.push(tmp);
            }
            for (int i = 0; i < 4; i++)
            {
                int nx = now.x + dir[i][0], ny = now.y + dir[i][1];
                if(!vis[nx][ny] && judge(nx, ny, now.size) && nx >= 1 + now.size / 2  && nx <= n - now.size / 2 && ny >= 1 + now.size / 2 && ny <= n - now.size / 2 && mp[nx][ny] == '+')
                {
                    node tmp = {nx, ny, now.size, now.t + 1};
                    q.push(tmp);
                    vis[nx][ny] = 1;
                }
            }
        }
    }
    int main()
    {
        cin >> n >> k;
        for (int i = 1; i <= n; i++)
            scanf("%s", mp[i] + 1);
        bfs();
        cout << ans;
        return 0;
    }
    
  • 相关阅读:
    html5 返回当前地理位置的坐标点(经纬度)
    C#趣味程序---百鸡百钱
    Android开发:怎样隐藏自己的app应用
    Android Studio一些简单设置
    集群通信组件tribes之集群的消息接收通道
    Java基础实例
    如何用webbrowser获取ajax动态生成的网页的源码?
    phantomjs 下拉滚动条获取网页的全部源码
    Nodejs+定时截图+发送邮件
    关注网页的更新状况,了解最新的handsup 消息.
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13970892.html
Copyright © 2011-2022 走看看