首页 > 技术文章 > U68862 奶牛滑迷宫

Wild-Donkey 2020-06-06 23:27 原文

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

推荐阅读