[洛谷 U68862] 奶牛滑迷宫 题解

说明:这原本是我很久之前出的一道题目。最近整理的时候发现这道题竟然还没写题解,就写了一下,顺便改&修了下题面。

题目描述

Farmer John的奶牛Besty进入了一个n*m的迷宫。

本题的特殊之处在于,Besty只能滑着走。具体来说就是,选定一个方向后,Besty会一直向该方向滑,直到撞到墙。

会给出Besty的起始位置。只需要滑出去即可。

求最小的撞墙次数。

输入格式

第一行两个整数n,m表示迷宫大小。

下面n行,每行m个整数,0表示空地,1表示墙。

最后一行两个整数sx,sy表示Besty初始位置。

输出格式

走出迷宫的最小撞墙次数。无解请输出-1。

样例

#1

输入

5 6
1 1 1 1 1 0
1 0 1 0 0 0
1 0 0 1 0 1
1 0 0 0 0 1
1 1 0 0 1 1
2 2

输出

3

#2

输入

5 3
1 1 1
1 0 1
0 0 1
1 0 1
1 1 1
2 2

输出

-1

数据范围

共16个测试点。其中前13个保证\(1\leq n,m\leq 30\)。最后3个保证\(1\leq n,m\leq 100\)

思路

别看题面整了这么个花样,但他毕竟还是个迷宫问题。再看数据范围,直接搜索就完事。

题解

正常的迷宫问题是每次把相邻的格子作为新的状态去搜索。

对于这道题目,我们也只需要从这个地方下手,把原本的搜索相邻格子变成搜索直到撞墙为止的格子即可。

代码实现上,我们可以跑一个while循环并维护当前位置,如果下一个格子是墙那么退出循环并把当前位置作为新的状态;否则往前走一步(把当前位置设为下一个格子)

代码

这里仅给出BFS的实现。DFS实现同理,核心代码是一样的。

#include <bits/stdc++.h>
using namespace std;
int n, m, sx, sy;
bool mat[501][501];
const int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
struct pos
{
    int x, y, step;
    pos(int x, int y, int step) : x(x), y(y), step(step) {}
};
queue<pos> q;
bool vis[501][501];
inline bool pan(int x, int y)
{
    return x >= 1 && x <= n && y >= 1 && y <= m && mat[x][y] == 0;
}
bool out(int x, int y)
{
    return (x == 1 || x == n || y == 1 || y == m) && mat[x][y] == 0;
}
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> mat[i][j];
        }
    }
    cin >> sx >> sy;
    if(mat[sx][sy]){
        cout<<-1;
        return 0;
    }
    if(out(sx,sy)){
        cout<<0;
        return 0;
    }
    q.push(pos(sx, sy, 0));
    vis[sx][sy] = 1;
    while (!q.empty())
    {
        pos h = q.front();
        q.pop();
        // cout << h.x << ' ' << h.y << endl;
        if (out(h.x, h.y))
        {
            cout << h.step - 1;
            return 0;
        }
        for (int i = 0; i < 4; i++)
        {
            int xx = h.x, yy = h.y;
            while (pan(xx + dx[i], yy + dy[i]))
            {
                xx += dx[i];
                yy += dy[i];
            }
            if ((xx == h.x && yy == h.y) || vis[xx][yy])
                continue;
            vis[xx][yy] = 1;
            q.push(pos(xx, yy, h.step + 1));
        }
    }
    cout << -1;
}
上一篇:OFDM留空*直流子载波的原理及实现


下一篇:Tram POJ - 1847 spfa