神殿
题目大意
用一个n∗mn∗mn∗m的矩阵,矩阵的每一个点都是一个房间,房间只有某些方向有门(见上图),要从一个房间走向相邻的房间必须要他们中间的两个门都是存在,也可以把所有房间的门顺时针旋转一轮。
走到相邻的房间要一个单位时间,旋转房间门也要一个时间单位。
现在问从(x1,y1)(x_1,y_1)(x1,y1)走到(x2,y2)(x_2,y_2)(x2,y2)最少需要多少各单位时间。
样例输入1
2 2
+*
*U
1 1 2 2
样例输出1
-1
样例输入2
2 3
<><
><>
1 1 2 1
样例输出2
4
数据范围
思路
这道题我们用bfsbfsbfs来做。
其实就是分为走到旁边的房间和旋转两种,具体看代码吧。
代码
#include<cstdio>
#include<queue>
using namespace std;
int n,m,x1,y1,x2,y2,dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
bool a[1501][1501][5],in[1501][1501][5];
char c;
struct note
{
int x,y,t,turn;
};
int abs(int x)
{
while (x<0) x=4+x;
return x;
}
void bfs()//bfs
{
queue<note>l;//建队列
l.push((note){x1,y1,0,0});//加入队列
in[x1][y1][0]=1;//标记
if (x1==x2&&y1==y2)//有没有到终点
{
printf("0");//输出
return ;//找到终点就可以退出了
}
while (l.size())
{
note x=l.front();//取出
l.pop();//用完就可以扔掉了
for (int i=0;i<4;i++)//枚举每一个走的方向
if (!in[x.x+dx[i]][x.y+dy[i]][x.turn])//是否没有走过
if (a[x.x][x.y][abs(i-x.turn)%4]&&a[x.x+dx[i]][x.y+dy[i]][abs(i-x.turn+2)%4])//是否中间的两个门都存在
if(x.x+dx[i]>0&&x.x+dx[i]<=n&&x.y+dy[i]>0&&x.y+dy[i]<=m)//是否超界
{
note y;
y.x=x.x+dx[i];//走到那个房间
y.y=x.y+dy[i];
y.t=x.t+1;//所需时间+1
y.turn=x.turn;//房间转的次数不变
in[y.x][y.y][y.turn]=1;//标记
l.push(y);//加入队列
if (y.x==x2&&y.y==y2)//是否到了终点
{
printf("%d",y.t);//输出
return ;//找到终点就可以退出了
}
}
if (!in[x.x][x.y][(x.turn+1)%4])//旋转
{
note y;
y.x=x.x;//房间不变
y.y=x.y;
y.t=x.t+1;//所需时间+1
y.turn=(x.turn+1)%4;//房间转的次数+1
in[y.x][y.y][y.turn]=1;//标记
l.push(y);//加入队列
if (y.x==x2&&y.y==y2)//是否到了终点
{
printf("%d",y.t);//输出
return ;//找到终点就可以退出了
}
}
}
printf("-1");//如果没有到就退出了,那么就说明找不到,输出-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++)
{
getchar();//处理换行符
for (int j=1;j<=m;j++)
{
c=getchar();//读入
if (c=='+')//打表
{
a[i][j][0]=1;
a[i][j][1]=1;
a[i][j][2]=1;
a[i][j][3]=1;
}
else if (c=='-')//打表
{
a[i][j][1]=1;
a[i][j][3]=1;
}
else if (c=='|')//打表
{
a[i][j][0]=1;
a[i][j][2]=1;
}
else if (c=='^')//打表
{
a[i][j][0]=1;
}
else if (c=='>')//打表
{
a[i][j][1]=1;
}
else if (c=='v')//打表
{
a[i][j][2]=1;
}
else if (c=='<')//打表
{
a[i][j][3]=1;
}
else if (c=='L')//打表
{
a[i][j][0]=1;
a[i][j][1]=1;
a[i][j][2]=1;
}
else if (c=='R')//打表
{
a[i][j][0]=1;
a[i][j][2]=1;
a[i][j][3]=1;
}
else if (c=='U')//打表
{
a[i][j][1]=1;
a[i][j][2]=1;
a[i][j][3]=1;
}
else if (c=='D')//打表
{
a[i][j][0]=1;
a[i][j][1]=1;
a[i][j][3]=1;
}
}
}
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);//读入
bfs();//bfs
// fclose(stdin);
// fclose(stdout);
return 0;
}