time limit per test3 seconds

memory limit per test256 megabytes

inputstandard input

outputstandard output

Theseus has just arrived to Crete to fight Minotaur. He found a labyrinth 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 has a button that rotates all blocks 90 degrees clockwise. Each block rotates around its center and doesn’t change its position in the labyrinth. Also, each block has some number of doors (possibly none). In one minute, Theseus can either push the button in order to rotate all the blocks 90 degrees clockwise or pass to the neighbouring block. Theseus can 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 in block (xT, yT) — the block in the row xT and column yT. Theseus know that the Minotaur is hiding in block (xM, yM) and wants to know the minimum number of minutes required to get there.

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 of the 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;

«*» means this block is a wall and has no doors.

Left, right, top and bottom are defined from representing labyrinth as a table, where rows are numbered from 1 to n from top to bottom and columns are numbered 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 the block where Minotaur is hiding have at least one door. Theseus and Minotaur may be 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 block where 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(1..4)次之后能通向临近的哪些点;

->结构体 can[x][y][旋转次数].up left right down

->别用数字代替方向0 0不然会晕。

然后用个flag数组判重下状态就好;

广搜的时候多了个旋转所有的方格的转移;

->有点像在4张图上做最短路;

感觉挺简单的。

代码有点长

#include <cstdio>
#include <queue> using namespace std; const int MAXN = 1050; struct abc
{
bool up, down, left, right;
}; struct abcd
{
int step, zhuangtai,x,y;
}; int n, m,xt,yt,xm,ym;
abc can[MAXN][MAXN][4];
queue <abcd> dl;
bool flag[MAXN][MAXN][4];
char s[MAXN]; bool inrange(int x, int y)
{
if (x <1 || x>n)
return false;
if (y<1 || y>m)
return false;
return true;
} bool judge(int x, int y)
{
return (x == xm && y == ym);
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%s", s);
for (int j = 1;j <= m;j++)
switch (s[j-1])
{
case '+':
{
for (int l = 0;l <= 3;l++)
for (int k = 0; k <= 3; k++)
{
can[i][j][l].up = true;
can[i][j][l].down = true;
can[i][j][l].left = true;
can[i][j][l].right = true;
}
break;
}
case '-':
{
can[i][j][0].left = true;
can[i][j][0].right = true;
can[i][j][1].up = true;
can[i][j][1].down = true;
can[i][j][2].left = true;
can[i][j][2].right = true;
can[i][j][3].up = true;
can[i][j][3].down = true;
break;
}
case'|':
{
can[i][j][0].up = true;
can[i][j][0].down = true;
can[i][j][1].left = true;
can[i][j][1].right = true;
can[i][j][2].up = true;
can[i][j][2].down = true;
can[i][j][3].left = true;
can[i][j][3].right = true;
break;
}
case'^':
{
can[i][j][0].up = true;
can[i][j][1].right = true;
can[i][j][2].down = true;
can[i][j][3].left = true;
break;
}
case'>':
{
can[i][j][0].right = true;
can[i][j][1].down = true;
can[i][j][2].left = true;
can[i][j][3].up = true;
break;
}
case '<':
{
can[i][j][2].right = true;
can[i][j][3].down = true;
can[i][j][0].left = true;
can[i][j][1].up = true;
break;
}
case 'v':
{
can[i][j][3].right = true;
can[i][j][0].down = true;
can[i][j][1].left = true;
can[i][j][2].up = true;
break;
}
case 'L':
{
can[i][j][0].up = true;
can[i][j][0].right = true;
can[i][j][0].down = true;
can[i][j][1].left = true;
can[i][j][1].right = true;
can[i][j][1].down = true;
can[i][j][2].up = true;
can[i][j][2].left = true;
can[i][j][2].down = true;
can[i][j][3].up = true;
can[i][j][3].left = true;
can[i][j][3].right = true;
break;
}
case 'R':
{
can[i][j][2].up = true;
can[i][j][2].right = true;
can[i][j][2].down = true;
can[i][j][3].left = true;
can[i][j][3].right = true;
can[i][j][3].down = true;
can[i][j][0].up = true;
can[i][j][0].left = true;
can[i][j][0].down = true;
can[i][j][1].up = true;
can[i][j][1].left = true;
can[i][j][1].right = true;
break;
}
case 'U':
{
can[i][j][3].up = true;
can[i][j][3].right = true;
can[i][j][3].down = true;
can[i][j][0].left = true;
can[i][j][0].right = true;
can[i][j][0].down = true;
can[i][j][1].up = true;
can[i][j][1].left = true;
can[i][j][1].down = true;
can[i][j][2].up = true;
can[i][j][2].left = true;
can[i][j][2].right = true;
break;
}
case 'D':
{
can[i][j][1].up = true;
can[i][j][1].right = true;
can[i][j][1].down = true;
can[i][j][2].left = true;
can[i][j][2].right = true;
can[i][j][2].down = true;
can[i][j][3].up = true;
can[i][j][3].left = true;
can[i][j][3].down = true;
can[i][j][0].up = true;
can[i][j][0].left = true;
can[i][j][0].right = true;
break;
}
case '*':
{
//wall
break;
}
}
}
scanf("%d%d", &xt, &yt);
scanf("%d%d", &xm, &ym);
flag[xt][yt][0] = true;
if (flag[xm][ym][0])
{
puts("0");
return 0;
}
abcd temp;
temp.step = 0;
temp.zhuangtai = 0;
temp.x = xt, temp.y = yt;
dl.push(temp);
while (!dl.empty())
{
abcd h = dl.front();
dl.pop();
int a0 = h.x, b0 = h.y, s = h.step, zt = h.zhuangtai;
int tempa0, tempb0;
//up
tempa0 = a0 - 1; tempb0 = b0;
if (inrange(tempa0, tempb0))
{
if (can[tempa0][tempb0][zt].down && can[a0][b0][zt].up)
{
if (!flag[tempa0][tempb0][zt])
{
flag[tempa0][tempb0][zt] = true;
abcd temph;
temph.x = tempa0, temph.y = tempb0, temph.step = s + 1, temph.zhuangtai = zt;
if (judge(tempa0, tempb0))
{
printf("%d\n", s + 1);
return 0;
}
dl.push(temph);
}
}
} //down
tempa0 = a0 +1; tempb0 = b0;
if (inrange(tempa0, tempb0))
{
if (can[tempa0][tempb0][zt].up && can[a0][b0][zt].down)
{
if (!flag[tempa0][tempb0][zt])
{
flag[tempa0][tempb0][zt] = true;
abcd temph;
temph.x = tempa0, temph.y = tempb0, temph.step = s + 1, temph.zhuangtai = zt;
if (judge(tempa0, tempb0))
{
printf("%d\n", s + 1);
return 0;
}
dl.push(temph);
}
}
} //left
tempa0 = a0; tempb0 = b0-1;
if (inrange(tempa0, tempb0))
{
if (can[tempa0][tempb0][zt].right && can[a0][b0][zt].left)
{
if (!flag[tempa0][tempb0][zt])
{
flag[tempa0][tempb0][zt] = true;
abcd temph;
temph.x = tempa0, temph.y = tempb0, temph.step = s + 1, temph.zhuangtai = zt;
if (judge(tempa0, tempb0))
{
printf("%d\n", s + 1);
return 0;
}
dl.push(temph);
}
}
} //right
tempa0 = a0; tempb0 = b0 + 1;
if (inrange(tempa0, tempb0))
{
if (can[tempa0][tempb0][zt].left && can[a0][b0][zt].right)
{
if (!flag[tempa0][tempb0][zt])
{
flag[tempa0][tempb0][zt] = true;
abcd temph;
temph.x = tempa0, temph.y = tempb0, temph.step = s + 1, temph.zhuangtai = zt;
if (judge(tempa0, tempb0))
{
printf("%d\n", s + 1);
return 0;
}
dl.push(temph);
}
}
} //change
tempa0 = a0; tempb0 = b0;
int newzt = (zt + 1) % 4;
if (!flag[tempa0][tempb0][newzt])
{
flag[tempa0][tempb0][newzt] = true;
abcd temph;
temph.x = tempa0, temph.y = tempb0, temph.step = s + 1, temph.zhuangtai = newzt;
dl.push(temph);
}
}
puts("-1");
return 0;
}

【25.93%】【676D】Theseus and labyrinth的更多相关文章

  1. 剑指Offer:合并两个排序的链表【25】

    剑指Offer:合并两个排序的链表[25] 题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 题目分析 每次都是比较箭头节点,把小节点连接到已经合 ...

  2. JAVA 基础编程练习题25 【程序 25 求回文数】

    25 [程序 25 求回文数] 题目:一个 5 位数,判断它是不是回文数.即 12321 是回文数,个位与万位相同,十位与千位相同. package cskaoyan; public class cs ...

  3. UI设计师零基础入门到精通精品视频教程【155课高清完整版】

    [福吧资源网分享]课程是非常完整的,也是非常零基础的,适合任何学员,有需要的可以下载看看!课程目录:第1章 Adobe Photoshop CS6课时1 Adobe Photoshop CS6入门基础 ...

  4. 【Android】【录音】Android录音--AudioRecord、MediaRecorder

    [Android][录音]Android录音--AudioRecord.MediaRecorder Android提供了两个API用于实现录音功能:android.media.AudioRecord. ...

  5. 【Xamarin开发 Android 系列 3】循序渐进的学习顺序

    原文:[Xamarin开发 Android 系列 3]循序渐进的学习顺序 指定合理的学习步骤,将各个技术点进行强化.慢慢 的就从点到线 到面的飞跃,一切仅仅是时间问题,开始前,请记住,学习是最佳的投资 ...

  6. 【iScroll源码学习01】准备阶段 - 叶小钗

    [iScroll源码学习01]准备阶段 - 叶小钗 时间 2013-12-29 18:41:00 博客园-原创精华区 原文  http://www.cnblogs.com/yexiaochai/p/3 ...

  7. 【WC2001】【cogs358】高性能计算机(动态规划)

    [WC2001][cogs358]高性能计算机(动态规划) ##题面 [问题描述] 现在有一项时间紧迫的工程计算任务要交给你--国家高性能并行计算机的主管工程师--来完成.为了尽可能充分发挥并行计算机 ...

  8. 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】

    Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...

  9. 【Python】【IO】

    # [[IO]] # [文件读写] '''读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的.读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现 ...

随机推荐

  1. 深入理解spring注解之@ComponentScan注解

    今天主要从以下几个方面来介绍一下@ComponentScan注解: @ComponentScan注解是什么 @ComponentScan注解的详细使用 1,@ComponentScan注解是什么 其实 ...

  2. Python 变量赋值

  3. 突破!阿里云CDN实现毫秒级全网刷新

    通常在某网站使用了CDN节点来实现内容分发加速后,当源站内容更新的时候,CDN刷新系统会通过提交刷新请求将CDN节点上的指定缓存内容强制过期.当用户访问的时候,CDN节点将回源获取最新内容返回给用户, ...

  4. Istio on ACK集成生态(2): 扩展AlertManager集成钉钉助力可观测性监控能力

    阿里云容器服务Kubernetes(简称ACK)支持一键部署Istio,可以参考文档在ACK上部署使用Isito.Istio on ACK提供了丰富的监控能力,为网格中的服务收集遥测数据,其中Mixe ...

  5. python MySQLdb用法,python中cursor操作数据库(转)

    数据库连接 连接数据库前,请先确认以下事项: 您已经创建了数据库 TESTDB. 在TESTDB数据库中您已经创建了表 EMPLOYEE EMPLOYEE表字段为 FIRST_NAME, LAST_N ...

  6. NSOperation 详解

    原文地址:http://nshipster.com/nsoperation/ 大家都知道的秘密是一个应用程序,瞬间响应卸载计算在后台异步完成.因此,现代的Objective-C开发者有两种选择:大中央 ...

  7. laravel多表登录出现路由调用错误

    public function auth() { // Authentication Routes... $this->get('login', 'Auth\LoginController@sh ...

  8. TP-admin即基于ThinkPHP5拿来即用高性能后台管理系统

    TP-Admin即基于ThinkPHP5的web后台管理系统(总结一套自己的后台管理系统,方便自己后续的项目开发.) 主要特性:自适应手机端.支持国际化.吸取其他CMF框架优点.多站点部署.日志记录. ...

  9. vue iframe嵌套页面高度自适应 (ios 宽度扩大的bug , ios展示比例问题)

    <template>   <div class="card-index pt-relative">     <div id="wrapper ...

  10. C# TransactionScope 事务类

    微软自带的TransactionScope(.Net Framework 2之后)是个好东东,提供的功能也很强大. 首先说说TransactionScope是什么,并能为我们做什么事情.其实看Tran ...