Codeforces 676D - Theseus and labyrinth 【BFS(二进制优化迷宫旋转)】


D. Theseus and labyrinth


time limit per test  3seconds
memory limit per test      256megabytes


Theseus has just arrived to Crete to fight Minotaur. He found alabyrinth that has a form of a rectangular field of size n × m and consists of blocks of size 1 × 1.

Each block of the labyrinth hasa button that rotates all blocks 90 degrees clockwise. Each block rotates around its center anddoesn't change its position in the labyrinth. Also, each block has some numberof doors (possibly none). In one minute, Theseus can either push the button inorder to rotate all the blocks 90 degrees clockwise or pass to the neighbouring block. Theseuscan go from block A to some neighbouring block B only if block A has a door that leads to block B and block B has a door that leads to block A.

Theseus found an entrance to labyrinth and is now located inblock (xT, yT) — the block in the row xT and column yT. Theseus know that theMinotaur is hiding in block (xM, yM) and wants to know the minimum number of minutes required to getthere.

Theseus is a hero, not a programmer, so he asks you to help him.

Input

The first line of the input contains two integers n and m (1 ≤ n, m ≤ 1000) —the number of rows and the number of columns in labyrinth, respectively.

Each of the following n lines contains m characters, describing the blocks ofthe labyrinth. The possible characters are:

·   «+»means this block has 4 doors (one door to each neighbouring block);

·   «-»means this block has 2 doors — to the left and to the right neighbours;

·   «|»means this block has 2 doors — to the top and to the bottom neighbours;

·   «^»means this block has 1 door — to the top neighbour;

·   «>»means this block has 1 door — to the right neighbour;

·   «<»means this block has 1 door — to the left neighbour;

·   «v»means this block has 1 door — to the bottom neighbour;

·   «L»means this block has 3 doors — to all neighbours except left one;

·   «R»means this block has 3 doors — to all neighbours except right one;

·   «U»means this block has 3 doors — to all neighbours except top one;

·   «D»means this block has 3 doors — to all neighbours except bottom one;

·   «*» meansthis block is a wall and has no doors.

Left, right, top and bottom are defined from representinglabyrinth as a table, where rows are numbered from 1 to n from top to bottom and columns arenumbered from 1 to m from left to right.

Next line contains two integers — coordinates of the block (xT, yT) (1 ≤ xT ≤ n, 1 ≤ yT ≤ m), where Theseus is initially located.

Last line contains two integers — coordinates of the block (xM, yM) (1 ≤ xM ≤ n, 1 ≤ yM ≤ m), where Minotaur hides.

It's guaranteed that both the block where Theseus starts and theblock where Minotaur is hiding have at least one door. Theseus and Minotaur maybe initially located at the same block.

Output

If Theseus is not able to get to Minotaur, then print -1 in the only line of the output.Otherwise, print the minimum number of minutes required to get to the blockwhere Minotaur is hiding.

Examples

Input

2 2
+*
*U
1 1
2 2

Output

-1

Input

2 3
<><
><>
1 1
2 1

Output

4

Note

Assume that Theseus starts at the block (xT, yT) at the moment 0


【题意】

有一个大小为n*m的迷宫,地图上每个房间都有一个符号,表示这个房间在上下左右哪些方向有门(可能一个也没有),你也可以把迷宫顺时针旋转90°,具体方式为所有房间绕自己的中心旋转,即旋转不改变每个房间的相对位置,只是改变了每个房间门的朝向,给出起点和终点,问从起点到终点最少需要多少分钟?(走一步,旋转一次都需要1分钟)


PS:A房间能走到B房间当且仅当A房间有通向B房间的门且B房间有通向A房间的门。


【思路】


用数组vis[i][j][st]表示到达(i,j)位置,且旋转的状态为st时的最少时间。


再用一个二进制数来表示每个房间初始时门的状态,规定方向与旋转方向相同,第一位为U,第二位为R,第三位为D,第四位为L。


如1101表示这个房间有向上,向右,向左的门。


接下来就BFS处理一下即可,每次有点入队时,先将它旋转一下再入队,然后再判断能否走到相邻房间。


判断方法:

  1. A房间有通向B房间的门

    mp[now.x][now.y]&(1<<(i+now.st)%4)

  2. B房间有通向A房间的门

    mp[nex.x][nex.y]&(1<<(i+2+nex.st)%4)


注意的是dir的方向设定要与二进制数低位到高位的顺序相同,结合判断条件理解即可。


#include <cstdio>
#include <queue>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long  ll;
const int maxn = 1005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f;
const double eps = 1e-9;
const int dir[4][2]={{0,-1},{1,0},{0,1},{-1,0}};  //跟二进制表示为倒序关系:LDRU 

int n,m;
int sx,sy,tx,ty;
char s[maxn];
int mp[maxn][maxn];
int vis[maxn][maxn][4];

struct node
{
    int x,y,time,st;
}now,nex;

int change(char x) // 顺序为URDL
{
    if(x=='*') return 0;
    if(x=='<') return 1;
    if(x=='v') return 2;
    if(x=='>') return 4;
    if(x=='^') return 8;
    if(x=='-') return 5;
    if(x=='|') return 10;
    if(x=='U') return 7;
    if(x=='R') return 11;
    if(x=='D') return 13;
    if(x=='L') return 14;
    if(x=='+') return 15;
}

bool inbound(const node &a)
{
    return a.x>=1&&a.x<=n&&a.y>=1&&a.y<=m;
}

int bfs()
{
    mst(vis,0);
    now.x=sx;
    now.y=sy;
    now.time=0;
    now.st=0;
    queue<node>q;
    q.push(now);
    vis[now.x][now.y][now.st]=1;
    while(q.size())
    {
        now=q.front();
        q.pop();
        if(now.x==tx&&now.y==ty)
        {
            return now.time;
        }
        if(vis[now.x][now.y][(now.st+1)%4]==0)
        {
            q.push(node{now.x,now.y,now.time+1,(now.st+1)%4});
            vis[now.x][now.y][(now.st+1)%4]=1;
        }
        for(int i=0;i<4;i++)
        {
            nex.x=now.x+dir[i][0];
            nex.y=now.y+dir[i][1];
            if(mp[nex.x][nex.y]!=0)
            {
                nex.st=now.st;
                if(inbound(nex)&&(mp[now.x][now.y]&(1<<(i+now.st)%4))&&(mp[nex.x][nex.y]&(1<<(i+2+nex.st)%4)))
                {
                    if(vis[nex.x][nex.y][nex.st]==0)
                    {
                        nex.time=now.time+1;
                        vis[nex.x][nex.y][nex.st]=1;
                        q.push(nex);
                    }
                }
            }
        }
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for(int j=1;j<=m;j++)
            {
                mp[i][j]=change(s[j]);
            }
        }
        scanf("%d%d",&sx,&sy);
        scanf("%d%d",&tx,&ty);
        int ans=bfs();
        printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值