题目链接:http://codeforces.com/problemset/problem/173/B
题意:
“密室再次被打开了。”——这个消息传遍了霍格沃茨,而一些学生因为看到蛇怪而被石化。虽然邓布利多被迫离开了学校,但哈利正尝试进入密室。而这对伏地魔可不是什么好消息。他不希望任何人进入密室。因为他正在吸取金妮的灵魂。
密室是一个n×m的矩形网格,其中一些单元格有柱子。光线(蛇怪的凝视)可以穿过柱子而不改变方向。但是通过一些魔咒,我们可以让柱子在接收光线时反射所有光线向四个方向射去。如下图所示。
![](https://i-blog.csdnimg.cn/blog_migrate/5ed559ab556783a0894143e91358e7cf.png)
左边光线穿过没有施魔法的柱子,右边光线穿过施魔法的柱子,效果如图。蛇怪在密室的右下角,向左边凝视。据传说,直接看见蛇怪的眼睛就会马上死亡,而看到通过柱子的反射光线就会被石化。我们知道,密室的入口在左上角,而进入的人必须注视他所要移动的方向。图片就是第一个样例。
![](https://i-blog.csdnimg.cn/blog_migrate/545df5b780e0139d6ddb1e36727db310.png)
给定密室的大小,和普通柱子的位置,伏地魔想要让你对最少的柱子施法,使所有人不能进入密室;或者表示不能完成保护密室的任务。
输入格式:
输入的第一行包含两个整数n和m (2<=n,<=1000)(2<=N,M<=1000)接下来n行每行包含m个字符。每个字符都是"."或"#"。表示密室的一个单元格。如果为"."表示为空,如果为"#"表示有柱子。
输出格式:
输出所需要施法的柱子在最小值,如果不可能完成,则输出"−1−1"。
说明:
图片为样例解释,将两根柱子都施魔法才可以阻止哈利进入密室。
思路:
一开始是想着从尾到头去搜索,然后分几个方向去遍历,后面看dalao的做法才知道是将行和列看成是点,当成是一个2行的数组作为去计算,目标就是到达第一行,如果说第一行有传送门的话,那必定可以转到向左的方向,所以就是从第n行到第1行的最短距离,因为有门才能连通,所以只要考虑门和门之间的联系就可以了。
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define ll long long
using namespace std;
const int N=1000005;
const int INF=0x3f3f3f3f;
int n,m;
struct node{
int now,to;
}edge[N*5];
int head[N],dis[N];
int idx=0;
queue<int> q;
void test(int x){
cout<<x<<endl;
}
void add(int u,int v){
edge[++idx].now=head[u];
edge[idx].to=v;
head[u]=idx;
}
void bfs()
{
q.push(1);
dis[1]=0;
while(!q.empty()){
int nowx=q.front();
q.pop();
for(int i=head[nowx];i;i=edge[i].now){
int y=edge[i].to;
if(dis[nowx]+1<dis[y]){
dis[y]=dis[nowx]+1;
q.push(y);
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
memset(dis,INF,sizeof(dis));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;
cin>>c;
if(c=='#'){
//行列看成2行 行作为1-n,列存放在n+1到2n
add(i,n+j);
add(n+j,i);
}
}
}
bfs();
if(dis[n]==INF){
cout<<"-1";
}
else cout<<dis[n];
return 0;
}
ps:在vj上提交是可以通过的,但是在洛谷上面会出现unknown error。