【BFS】神殿

神殿

题目大意

n∗mn*mnm的矩阵中,有些房间会有些门,但要有两边的房间的左边和右边都有门才能通过,通过的时间要1分钟,问从(x,y)(x,y)xy起始点到终点最少要多少,如果行不通可以把整个地图给顺时针旋转90度,如果真的不行就输出-1.

输入

第一行 n和m
下面n∗mn*mnm个字符
在这里插入图片描述
最后输入x,y和x2,y2.

输出

最短时间,如果不行就输出-1

输入样例

2 2
+*
*U
1 1 2 2

输出样例

-1

解题思路

其实这道题就是一道BFS,码量一点都不小(只是打了半天而已),就两百多行吧!!!
BFS来搜是否可以通过即可.
具体讲解在代码!!!

程序如下

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,w[4000001][11],x1,x2,y1,y2,r[4000001]; 
bool p[1001][1001][11];
const int next[4]={1,2,3,0};
char b[1001][101];
struct node
{
	bool down[1001][1001],up[1001][1001],right[1001][1001],left[1001][1001];
}a[4];
void bfs()
{
	int h=0,t=1,x,y,z;
	w[1][0]=x1;
	w[1][1]=y1;
	w[1][2]=0;														
	while(h<t)
	{
		h++;
		x=w[h][0];
		y=w[h][1];
		z=w[h][2];
		
		if(x==x2&&y==y2)//判断是否到达了
		{
			printf("%d",r[h]);
			return ;
		}
		if(x+1<=n)/./判断是否出界
		{
			if(a[z].down[x][y]==1&&a[z].up[x+1][y]==1&&p[x+1][y][z]==0)//判断是否可以走到下一个房间
			{
				t++;
				w[t][0]=x+1;
				w[t][1]=y;
				w[t][2]=z;
				r[t]=r[h]+1;
				p[x+1][y][z]=1;
			}
		}
		
		if(x-1>=1)
		{
			if(a[z].down[x-1][y]==1&&a[z].up[x][y]==1&&p[x-1][y][z]==0)//同上
			{
				t++;
				w[t][0]=x-1;
				w[t][1]=y;
				w[t][2]=z;
				r[t]=r[h]+1;
				p[x-1][y][z]=1;
			}
		}
		
		if(y+1<=m)
		{
			if(a[z].right[x][y]==1&&a[z].left[x][y+1]==1&&p[x][y+1][z]==0)//同上
			{
				t++;
				w[t][0]=x;
				w[t][1]=y+1;
				w[t][2]=z;
				r[t]=r[h]+1;
				p[x][y+1][z]=1;
			}
		}
		
		if(y-1>=1)
		{
			if(a[z].right[x][y-1]==1&&a[z].left[x][y]==1&&p[x][y-1][z]==0)//同上
			{
				t++;
				w[t][0]=x;
				w[t][1]=y-1;
				w[t][2]=z;
				r[t]=r[h]+1;
				p[x][y-1][z]=1;
			}
		}
		if(p[x][y][next[z]]==0)
		{
			t++;
			w[t][0]=x;
			w[t][1]=y;
			w[t][2]=next[z];
			r[t]=r[h]+1;
			p[x][y][next[z]]=1;
		}
	}
	printf("-1");
}
int main()
{
	freopen("temple.in","r",stdin);
	freopen("temple.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
		{
			cin>>b[i][j];
			if(b[i][j]=='+')
			{
				a[0].down[i][j]=1;//标记每个房间是否有门
				a[0].up[i][j]=1;//同上
				a[0].right[i][j]=1;//同上
				a[0].left[i][j]=1;//同上
			}
			if(b[i][j]=='-')
			{
				a[0].down[i][j]=0;//同上
				a[0].up[i][j]=0;//同上
				a[0].right[i][j]=1;//同上
				a[0].left[i][j]=1;//同上
			}
			if(b[i][j]=='|')
			{
				a[0].down[i][j]=1;//同上
				a[0].up[i][j]=1;//同上
				a[0].right[i][j]=0;//同上
				a[0].left[i][j]=0;//同上
			}
			if(b[i][j]=='^')
			{
				a[0].down[i][j]=0;//同上
				a[0].up[i][j]=1;//同上
				a[0].right[i][j]=0;//同上
				a[0].left[i][j]=0;//同上
			}
			if(b[i][j]=='<')
			{
				a[0].down[i][j]=0;//同上
				a[0].up[i][j]=0;//同上
				a[0].right[i][j]=0;//同上
				a[0].left[i][j]=1;//同上
			}
			if(b[i][j]=='>')
			{
				a[0].down[i][j]=0;//同上
				a[0].up[i][j]=0;//同上
				a[0].right[i][j]=1;//同上
				a[0].left[i][j]=0;//同上
			}
			if(b[i][j]=='v')
			{
				a[0].down[i][j]=1;//同上
				a[0].up[i][j]=0;//同上
				a[0].right[i][j]=0;//同上
				a[0].left[i][j]=0;//同上
			}
			if(b[i][j]=='L')
			{
				a[0].down[i][j]=1;//同上
				a[0].up[i][j]=1;//同上
				a[0].right[i][j]=1;//同上
				a[0].left[i][j]=0;//同上
			}
			if(b[i][j]=='R')
			{
				a[0].down[i][j]=1;//同上
				a[0].up[i][j]=1;//同上
				a[0].right[i][j]=0;//同上
				a[0].left[i][j]=1;//同上
			}
			if(b[i][j]=='U')
			{
				a[0].down[i][j]=1;//同上
				a[0].up[i][j]=0;//同上
				a[0].right[i][j]=1;//同上
				a[0].left[i][j]=1;//同上
			}
			if(b[i][j]=='D')
		    {
				a[0].down[i][j]=0;//同上
			    a[0].up[i][j]=1;//同上
				a[0].right[i][j]=1;//同上
				a[0].left[i][j]=1;//同上
			}
			if(b[i][j]=='*')
		    {
				a[0].down[i][j]=0;//同上
			    a[0].up[i][j]=0;//同上
				a[0].right[i][j]=0;//同上
				a[0].left[i][j]=0;//同上
			}
		}
	}
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
		{
			for(int k=1;k<=3;++k)
			{
				if(a[k-1].down[i][j]) a[k].left[i][j]=1;//判断是否为旋转
				else  a[k].left[i][j]=0;
				if(a[k-1].left[i][j]) a[k].up[i][j]=1;//同上
				else a[k].up[i][j]=0;
				if(a[k-1].right[i][j]) a[k].down[i][j]=1;//同上
				else a[k].down[i][j]=0;
				if(a[k-1].up[i][j]) a[k].right[i][j]=1;//同上
				else a[k].right[i][j]=0;
			}
		}
	}
	scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    bfs();//BFS
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值