Chamber of Secrets

传送门

"The Chamber of Secrets has been opened again" — this news has spread all around Hogwarts and some of the students have been petrified due to seeing the basilisk. Dumbledore got fired and now Harry is trying to enter the Chamber of Secrets. These aren't good news for Lord Voldemort. The problem is, he doesn't want anybody to be able to enter the chamber. The Dark Lord is going to be busy sucking life out of Ginny.

The Chamber of Secrets is an n × m rectangular grid in which some of the cells are columns. A light ray (and a basilisk's gaze) passes through the columns without changing its direction. But with some spell we can make a column magic to reflect the light ray (or the gaze) in all four directions when it receives the ray. This is shown in the figure below.

The left light ray passes through a regular column, and the right ray — through the magic column.

The basilisk is located at the right side of the lower right cell of the grid and is looking to the left (in the direction of the lower left cell). According to the legend, anyone who meets a basilisk's gaze directly dies immediately. But if someone meets a basilisk's gaze through a column, this person will get petrified. We know that the door to the Chamber is located on the left side of the upper left corner of the grid and anyone who wants to enter will look in the direction of its movement (in the direction of the upper right cell) from that position.

This figure illustrates the first sample test.

Given the dimensions of the chamber and the location of regular columns, Lord Voldemort has asked you to find the minimum number of columns that we need to make magic so that anyone who wants to enter the chamber would be petrified or just declare that it's impossible to secure the chamber.

Input

The first line of the input contains two integer numbers n and m (2 ≤ n, m ≤ 1000). Each of the next n lines contains m characters. Each character is either "." or "#" and represents one cell of the Chamber grid. It's "." if the corresponding cell is empty and "#" if it's a regular column.

Output

Print the minimum number of columns to make magic or -1 if it's impossible to do.

Examples

input

3 3
.#.
...
.#.

output

2

input

4 3
##.
...
.#.
.#.

output

2

Note

The figure above shows the first sample test. In the first sample we should make both columns magic. The dragon figure represents the basilisk and the binoculars represent the person who will enter the Chamber of secrets. The black star shows the place where the person will be petrified. Yellow lines represent basilisk gaze moving through columns.

题意:

给你一个 n * m 的无向图 ,一束激光从左上角(1,1) 向右出发 , 每经过一次 "#" ,你可以选择仍按原方向前进, 或者消耗一次代价,使他向任意方向反射, 问你是否能到达右下角(n,m)并向右射出,如果可以输出最小代价,否则输出-1

思路一:双端BFS

双端BFS适用于 边权为 0 或 1 的搜索, 此题比较有意思的是,我们要存一下,激光的方向.另外 开一个数组p[x][y][dir] 表示当前状态的代价,记得初始化为inf

用双端队列去存 当前激光所在坐标及方向 , 每当我们经过一次'#',我们可以选择操作他反射,并改变他的方向,并使他的 pnow = pfront + 1 ,入队要入尾;

当我们选择不操作他反射时,只需要更新 坐标信息 ,方向和代价均保持不变 ,入队要入头;

见代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <queue>
#include <vector>
#define endl '\n'
using namespace std;
void IOS(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
typedef pair<int,int> PII;
typedef long long ll;
const int maxn=5e5+5;
const int inf =0x3f3f3f3f;
int n,m;
char ch[1005][1005];
int p[1005][1005][4];
int dx[4] = {0,1,-1,0};
int dy[4] = {1,0,0,-1};
struct node{
int x,y;
int dir;
// 0 右 1 下 2 上 3 左
}front,now;
bool check(int x,int y)
{
if(x >= 1 && x <= n && y >= 1 && y <= m)
{
return true;
}
return false;
}
int bfs()
{
deque<node>dq;
dq.push_back({1,1,0});
p[1][1][0] = 0;
while(!dq.empty())
{
front = dq.front();
dq.pop_front();
int x = front.x;
int y = front.y;
if(x == n && y == m && front.dir == 0)
{
break;
}
if(x == n && y == m && ch[x][y] == '#' && front.dir != 0)
{
p[x][y][0] = p[x][y][front.dir] + 1;
break;
}
//把不操作的放在队首 int xx = x + dx[front.dir];
int yy = y + dy[front.dir];
if(check(xx,yy) && p[xx][yy][front.dir] == inf)
{
now.x = xx;
now.y = yy;
now.dir = front.dir;
p[xx][yy][now.dir] = p[x][y][front.dir];
dq.push_front(now); } //操作的放在队尾
if(ch[x][y] == '#')
{
for(int i = 0; i < 4 ; i ++)
{
int xx = x + dx[i];
int yy = y + dy[i];
if(check(xx,yy) && p[xx][yy][i] == inf)
{
now.x = xx;
now.y = yy;
now.dir = i;
p[xx][yy][now.dir] = p[x][y][front.dir] + 1;
dq.push_back(now); }
} }
}
if(p[n][m][0] == inf)
return -1;
else
return p[n][m][0];
}
int main(){
memset(p,inf,sizeof(p)); scanf("%d%d",&n , &m);
for(int i = 1; i <= n; i ++)
{
scanf("%s",ch[i]+1);
}
int t = bfs();
printf("%d\n", t);
return 0;
}

思路二:SPFA() 最短路

以行和列建二分图,如果ch[i][j]=='#',则从i节点到j节点建一条双向边,权值都为1。然后对二分图跑一遍最短路。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <queue>
#include <vector>
#define endl '\n'
using namespace std;
void IOS(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
typedef pair<int,int> PII;
typedef long long ll;
const int maxn=2e6+5;
const int inf = 0x3f3f3f3f;
int n,m,tol,head[maxn];
int p[maxn];
char ch[1005][1005];
struct node{
int to;
int cost;
int next;
}edge[maxn];
void add(int u,int v,int w)
{
edge[tol].to=v;
edge[tol].cost=w;
edge[tol].next=head[u];
head[u]=tol++;
}
int spfa(int s)
{
queue<int>q;
p[s] = 0;
q.push(s);
while(!q.empty())
{
int v=q.front();
q.pop();
for(int i = head[v]; i != -1 ; i = edge[i].next)
{
node e = edge[i];
if(p[e.to] > p[v] + e.cost)
{
p[e.to] = p[v] + e.cost;
q.push(e.to);
}
}
}
if(p[n] == inf)
return -1;
else
return p[n];
}
int main(){
memset(head,-1,sizeof(head));
memset(p,inf,sizeof(p)); scanf("%d%d",&n , &m);
for(int i = 1; i <= n; i ++)
{
scanf("%s",ch[i]+1);
}
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m ; j ++)
{
if(ch[i][j] == '#')
{
add(i,j+n,1);
add(j+n,i,1);
}
}
}
int t = spfa(1);
printf("%d\n", t);
return 0;
}

Chamber of Secrets 双端队列广搜BFS 与 SPFA两种解法的更多相关文章

  1. 用Python实现的数据结构与算法:双端队列

    一.概述 双端队列(deque,全名double-ended queue)是一种具有队列和栈性质的线性数据结构.双端队列也拥有两端:队首(front).队尾(rear),但与队列不同的是,插入操作在两 ...

  2. Python实现的数据结构与算法之双端队列详解

    一.概述 双端队列(deque,全名double-ended queue)是一种具有队列和栈性质的线性数据结构.双端队列也拥有两端:队首(front).队尾(rear),但与队列不同的是,插入操作在两 ...

  3. POJ3662 SPFA//二分 + 双端队列最短路

    https://cn.vjudge.net/problem/12427/origin 题意:求1到N第K + 1大条边权最小的路径 首先想到dp递推,dp[x][y]表示到x这个点经过y条免费边的最小 ...

  4. POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】

    <题目链接> 题目大意: 在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小. 解题分析:直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+ ...

  5. 电路维修 (广搜变形-双端队列bfs)

    # 2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On [题目描述] 有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会 ...

  6. P4554 小明的游戏 (洛谷) 双端队列BFS

    最近没有更新博客,全是因为英语,英语太难了QWQ 洛谷春令营的作业我也不会(我是弱鸡),随机跳了2个题,难度不高,还是讲讲吧,学学新算法也好(可以拿来水博客) 第一题就是这个小明的游戏 小明最近喜欢玩 ...

  7. codeforces 1064D 双端队列BFS

    双端队列BFS解决的就是路径权值可能为0的图最短路问题,权值为0插入队头,否则插入队尾. 对于这个题,可以看作上下移动的路径的权值为0,左右移动权值为1,而且不能超过规定的步数. 直接广搜求覆盖的点的 ...

  8. 双端队列-deque【集vector与list于一身的牺牲内存换功能完善】

    看到双端队列(deque)了,书上是这样说的:除了栈和队列外还有一种限定性数据结构是双端队列:双端队列是限定插入和删除操作在表的两端进行的线性表:尽管双端队列看起来似乎比栈和队列更灵活,但实际上在应用 ...

  9. lintcode二叉树的锯齿形层次遍历 (双端队列)

    题目链接: http://www.lintcode.com/zh-cn/problem/binary-tree-zigzag-level-order-traversal/ 二叉树的锯齿形层次遍历 给出 ...

  10. lintcode 滑动窗口的最大值(双端队列)

    题目链接:http://www.lintcode.com/zh-cn/problem/sliding-window-maximum/# 滑动窗口的最大值 给出一个可能包含重复的整数数组,和一个大小为  ...

随机推荐

  1. DateValue转换日期文本的一个注意问题

    Excel 中,DateValue转换日期文本,遇到欧式日期格式:"17 Jun 2025"或"Jun 17, 2025"这样的日期需要转换时,一定要注意,日. ...

  2. 故障处理:Oracle一体机更换磁盘控制器后部分磁盘状态异常的案例处理

    我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效 ...

  3. 前端开发系列100-小程序篇之UI组件库的使用和封装

    本文介绍微信小程序开发中常用的第三方UI组件库的基本使用流程和如何自定义组件. 1.0 第三方UI组件库的基本使用流程 通常,在使用第三方组件库之前首先需要通过代码的托管仓库和组件库文档来了解该组件库 ...

  4. QN 笔试反思 HL笔试 反思

    先写 HL的笔试题目 int a[4]; a++;是错的  因为  a代表了一个常量的地址. 百度解释: 对于一维数组,数组名代表的是数组的首地址,而且数组名是一个常量地址,也就是说数组名的地址是不可 ...

  5. C2065错误

    简介 应该是编译器出现了问题 有的时候 我加入注释就会报错.贼烦人.算了 还是用英文写注释没毛病. 其实核心解决方案 https://blog.csdn.net/weixin_43975504/art ...

  6. iPaaS 与 API 管理:企业数字化转型的双引擎

    一.企业集成的残酷现实 根据IDC 2024 年数字化转型报调研显示:大中型企业平均部署数十至数百个业务系统,涵盖 ERP.CRM.SaaS 应用及物联网平台等,但仅约 30% 的系统实现标准化集成. ...

  7. API可视化编排,提高API可复用率

    在数字化时代,API(应用程序编程接口)已成为不同软件应用之间沟通的桥梁.然而,如何高效管理.编排和复用这些API,成为了企业和开发者面临的重要挑战.随着技术的不断进步,RestCloud API可视 ...

  8. SciTech-Mathmatics-Probability+Statistics-Population-Sampling-Types of Sampling Methods (With Examples)

    Types of Sampling Methods (With Examples) BY ZACH BOBBITTPOSTED ON SEPTEMBER 24, 2018 Researchers ar ...

  9. flink 1.11.2 学习笔记(2)-Source/Transform/Sink

    一.flink处理的主要过程 从上一节wordcount的示例可以看到,flink的处理过程分为下面3个步骤: 1.1 .添加数据源addSource,这里的数据源可以是文件,网络数据流,MQ,Mys ...

  10. Linux 系统目录结构-九五小庞

    在 Linux 系统中,有几个目录是比较重要的,平时需要注意不要误删除或者随意更改内部文件. /etc: 上边也提到了,这个是系统中的配置文件,如果你更改了该目录下的某个文件可能会导致系统不能启动. ...