1. 程式人生 > 實用技巧 >AcWing 2548. 大胖子走迷宮(BFS)

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;
}