U68364 _GC滑迷宫

题目背景

_GC买了一双蔡徐坤一代。

题目描述

_GC进入了一个n*m的迷宫。
本题的特殊之处在于,_GC只能滑着走。具体来说就是,选定一个方向后,_GC会一直向该方向滑,直到撞到墙。
会给出_GC的起始位置。只需要滑出去即可。
求最小的撞墙次数。

输入输出格式

输入格式:

第一行两个整数n,m表示迷宫大小。
下面n行,每行m个整数,0表示空地,1表示墙。
最后一行两个整数sx,sy表示_GC初始位置。

输出格式:

走出迷宫的最小撞墙次数。无解请输出-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
输出样例#1: 复制
3
输入样例#2: 复制
5 3
1 1 1
1 0 1
0 0 1
1 0 1
1 1 1
2 2
输出样例#2: 复制
-1

说明

1leq n,mleq 201n,m20 由于出题人太菜不会自动生成数据,数据都是手算的,可能有锅+很水

………………………………………………分割线~………………………………………………………

话说此题非常有趣啊,竟然是以我们的童鞋的大名为题......

好了进入正题:

既然是走迷宫的题目,那么此题应该就是一个搜索题,毋庸置疑吧。

但是和其他迷宫题不同的是:这个笨拙_GC竟然要滑到墙上

那也好办,就比普通的迷宫题多了个步骤:只要前方没有障碍物,就让他一直滑下去,直到撞墙残忍,所用步数还是为1

            int xx=h.x,yy=h.y;                    //记录这个点的位置 
            while(pd(xx+dx[i],yy+dy[i]))          //如果这个方向没有障碍物,一直滑下去,pd是判断是否在迷宫内且当前方向的前方是否有障碍物 
            {
                xx+=dx[i];
                yy+=dy[i];
            }

解决完这个问题,就可以上代码啦:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
int m,n,sx,sy;
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};                    //四个方向
bool a[25][25],vis[25][25];                               //a数组存放迷宫,vis数组存放当前点是否到达过
struct pos                                                //定义pos结构体,里面有横纵坐标及到达该点所撞墙的次数
{
    int x,y,step;
    pos(int x,int y,int step) : x(x),y(y),step(step){}    //构造函数,意思是将括号里的值赋给外面的变量
};
queue<pos> q;                                             //定义q队列,用到的头文件就是#include<queue>
inline bool pd(int x,int y)                               //判断当前点是否在迷宫里且当前方向的前方是否有障碍物 
{ 
     return x>=1&&x<=m&&y>=1&&y<=n&&a[x][y]==0;           //如果为真,返回1;如果为假,返回0
}
bool out(int x,int y)                                     //判断_GC是否能滑出迷宫
{
     return (x==1||x==m||y==1||y==n)&&a[x][y]==0;
}
int main()
{
    cin>>m>>n;
    for(int i=1;i<=m;i++)
       for(int j=1;j<=n;j++)
       scanf("%d",&a[i][j]);
    cin>>sx>>sy;                                  //起点坐标
    if(a[sx][sy]==1) {cout<<-1;return 0;}         //神奇的卡墙,判无解 
    if(out(sx,sy)==1) {cout<<0;return 0;}         //如果本来就在出口,那么撞墙数为0 
    q.push(pos(sx,sy,0));                         //将起点位置入队,并将坐标位置和撞墙次数赋值 
    vis[sx][sy]=1;                                //将起点位置标记为“1”
    while(!q.empty())                             //判队列是否为空 
    {
        pos h=q.front();                          //记录队首元素 
        q.pop();                                  //队首元素出队 
        if(out(h.x,h.y)==1) {cout<<h.step-1;return 0;}
        for(int i=0;i<4;i++)                      //四个方向 
        {
            int xx=h.x,yy=h.y;                    //记录这个点的位置 
            while(pd(xx+dx[i],yy+dy[i]))          //如果这个方向没有障碍物,一直滑下去 
            {
                xx+=dx[i];
                yy+=dy[i];
            }
            if((xx==h.x&&yy==h.y)||vis[xx][yy]==1) continue;    //如果位置没变或到达的位置已经遍历过,换方向 
            vis[xx][yy]=1;                        //将滑完后的点标记为 
            q.push(pos(xx,yy,h.step+1));          //将滑完后的位置入队 
        }
    }
    cout<<-1;                                     //如果所有点都被遍历过且都为走出,则说明无解
    return 0;
}

蒟蒻刚学搜索,如果有错请诸位大佬们指出,谢谢qaq!

原文地址:https://www.cnblogs.com/xcg123/p/10705645.html