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
输出 #1
3
输入 #2
5 3
1 1 1
1 0 1
0 0 1
1 0 1
1 1 1
2 2
输出 #2
-1
说明/提示
共16个测试点。其中前13个保证1≤n,m≤30。最后3个保证1≤n,m≤100
题解
如果是一般的迷宫最短路, 标准解法都是BFS, 但是相比BFS, 显然DFS更容易实现, 所以在数据不大的时候, 一般会选择DFS解这类题. 但是考虑到这个题的特殊性, 一个点的最少步数可能被任何同一行或同一列的点更新, 而不是像一般的迷宫一样只能被相邻的点更新, 所以就导致了这个题用DFS不能(或很难, 没有证明的时候不能说的太绝对, 但是毕竟没有人成功过)做出.
只要使用BFS就能轻松过.
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
int n,m,f[1005][1005],sx,sy,qx[10005],qy[10005],fx[5]={0,1,0,-1,0},fy[5]{0,0,1,0,-1};
bool a[1005][1005],flg=0;
char ch;
string s;
void bfs(int x,int y){
int l=1;
int r=1;
f[x][y]=0;
qx[r]=x;
qy[r]=y;
while(l<=r){
x=qx[l];
y=qy[l];
l++;//起点出队
for(int i=1;i<=4;i++){//四个方向
int nx=x,ny=y;
while(!(a[nx+fx[i]][ny+fy[i]])){//不碰壁就一直走下去
nx+=fx[i];
ny+=fy[i];
if((nx<=0)||(nx>n)||(ny<=0)||(ny>m)){//这里不判断会RE
cout<<f[x][y]<<endl;//出界就是走出迷宫的答案, 只要输出来时的节点就可, 因为出迷宫不会碰壁, 下同
flg=1;
return;
}
}
if((nx<=0)||(nx>n)||(ny<=0)||(ny>m)){//同样是判断边界
cout<<f[x][y]<<endl;
flg=1;
return;
}
if((!(f[nx][ny]))&&(!((nx==sx)&&(ny==sy)))){
f[nx][ny]=f[x][y]+1;//从上层节点来的, 碰壁后停下, 所以比上层多碰一次
r++;
qx[r]=nx;
qy[r]=ny;//入队
}
}
}
return;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
cin>>sx>>sy;
bfs(sx,sy);
if(!flg){//搜完之后没有出界的路径
cout<<-1<<endl;
}
return 0;
}