本题的特殊之处在于,_GC只能滑着走。具体来说就是,选定一个方向后,_GC会一直向该方向滑,直到撞到墙。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include <bits/stdc++.h>
using namespace std;
int n,m,sx,sy;
int dx[4]={-1,1,0,0},
dy[4]={0,0,-1,1};
bool bz[501][501];
bool vis[501][501];
struct pos
{
int x,y,step;
pos(int xx,int yy,int stepp) : x(xx),y(yy),step(stepp) {}
//构造函数,把xx赋值给x(后边也是);
};
queue<pos> q; //定义一个pos类型的队列q
bool pan(int x,int y) //判断合法性(防止出现_GC卡在墙里)
{
return x>=1&&x<=n&&y>=1&&y<=m&&bz[x][y]==0;
}
bool out(int x,int y) //判断是否已到达迷宫边界,即可以离开迷宫
{
return (x==1||x==n||y==1||y==m)&&bz[x][y]==0;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>bz[i][j];
cin>>sx>>sy;
if(bz[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(); //把队首元素的三个值全部赋值给h
q.pop(); //队首出队
if(out(h.x,h.y)) //如果到达出口
{
cout<<h.step-1; //因为原题求的是撞墙次数,而我们知道最后一次是不撞墙的
return 0; //直接退出,因为已求得最优解
}
for(int i=0;i<=3;i++)
{
int xx=h.x,yy=h.y;
while(pan(xx+dx[i],yy+dy[i])) //如果没撞到墙,就继续走
{
xx+=dx[i]; //_GC要一直滑啊滑
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; //如果所有可能节点都已遍历,而始终没有到达边界,则无解
}