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. PHPCMS快速建站系列之 pc标签where中如何使用变量

    {pc:content action="lists" catid="$catid" where="typeid='$t'" order=&q ...

  2. JavaScript实现,控制一个文本框只能输入正整数,如输入不符合条件则文本框全部字体标红

    腾讯2014年研发职位笔试题Web前端方向简单题第一题. 代码: <html> <head> <title>test JavaScript</title> ...

  3. MUI - 解决弹出输入法时页面高度变小导致底部上浮的问题

    解决弹出输入法时页面高度变小导致底部上浮的问题 在有输入框的页面,当输入法弹出的时候,底部元素上浮遮盖了输入框,影响页面美观及功能.查找了一下,页面变窄是不可避免的.即使是设置绝对固定也是不可以的.因 ...

  4. inflate用一个XML源填充view. LayoutInflater

    java.lang.Object     android.view.LayoutInflater This class is used to instantiate layout XML file i ...

  5. python的str,unicode对象的encode和decode方法, Python中字符编码的总结和对比bytes和str

    python_2.x_unicode_to_str.py a = u"中文字符"; a.encode("GBK"); #打印: '\xd6\xd0\xce\xc ...

  6. 实践分享:开始用Cordova+Ionic+AngularJS开发App

    http://www.cocoachina.com/webapp/20150707/12395.html 本文是一篇关于我本人在使用Cordova+Ionic以及AngularJS开发移动App的过程 ...

  7. 2019-7-25-VisualStudio-2019-新创建项目添加-git-仓库

    title author date CreateTime categories VisualStudio 2019 新创建项目添加 git 仓库 lindexi 2019-7-25 15:8:15 + ...

  8. oracle函数 localtimestamp

    [功能]:返回会话中的日期和时间 [参数]:没有参数,没有括号 [返回]:日期 [示例]select localtimestamp from dual; 返回:14-11月-08 12.35.37.4 ...

  9. H3C TCP/UDP端口号

  10. 深入java面向对象五:Java的内存管理

    一. Java对象的引用种类 Java内存管理包括内存分配和内存回收, 这个动作都是由JVM自动完成,所以过多的内存分配增加了内存的消耗,且垃圾回收线程的不断运行会给后台增加压力,降低系统的性能. 1 ...