题目描述
CYJ想找到他的小伙伴FPJ,.CYJ和FPJ现在位于一个房间里,这个房间的布置可以看成一个N行M列的矩阵,矩阵内的每一个元素会是下列情况中的一种:
1.障碍区域—这里有一堵墙(用‘#’表示).
2.这是CYJ最开始在的区域(用‘C’表示).
3.这是FPJ在的区域(用‘F’表示).
4.空区域(用‘.’表示).
CYJ携带了一个所谓传送枪的东西,这是一把可以创造传送门的枪械,在每一次行动中,他可以选择下列操作中的一项:
1.移向一个相邻的格子中(上,下,左,右,不能移到墙在的格子里).这个操作要消耗一个单位的时间.
2.转向一个墙(不需要相邻,只需面向即可),向其发射传送门,传送门会留在墙内面向你的地方(至多只能同时存在两扇传送门),若墙上已经有两扇传送门,而你发射了第三扇,那么最初发射的那一扇会消失。同时,你无法在一个位置制造两扇传送门(这个操作不会耗费时间)。
3.如果他与一块墙壁相邻且面前有一扇传送门,那么他可以移动到另一扇传送门前方的格子。这个操作会耗费一个单位的时间.
CYJ想要知道自己最少需要多少时间才能够从起点(‘C’)到达终点(‘F’).
请注意:我们保证地图边缘会是一圈墙壁且一定存在‘C’,‘F’.
输入
第一行输入两个正整数 N 和 M ,(4 ≤ N,M ≤ 500).表示地图大小。
接下来的N行每行一个长度为M的字符串.表示地形。
输出
你需要输出最少的到达终点的时间,如果不能到达请输出”no”。
样例输入
【样例1】
4 4
#.F#
#C.#
【样例2】
6 8
########
#.##…F#
#C.##…#
#…#…#
#…##
########
【样例3】
4 5
#C#.#
###F#
样例输出
【样例1】
2
【样例2】
4
【样例3】
no
提示
样例2解释:
从C点(3,2)开始,我们首先向左发射传送门,再向下发射传送门,向左进入传送门,到达(5,2),向右发射传送门,向下进入传送门,到达(5,6),向上发射传送门,向右进入传送门,到达(2,6),向右移动,到达F.
【数据范围】
50%的数据满足:4<= N,M <=15;
100%的数据满足:4<= N,M <=500;
思路
对每个非墙点,都有至多八种方式连边,即向上下左右四个方向走一步,或向上下左右四个方向的墙面最近点移动,在连边后,直接跑dijkstra即可
代码实现
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=505;
const int M=3e5;
const int INF=0x3f3f3f3f;
const ll LINF=1e18;
const ull sed=31;
const ll mod=998244353;
const double eps=1e-7;
const double PI=3.14159265358979;
typedef pair<int,int>P;
typedef pair<double,double>Pd;
template<class T>void read(T &x)
{
x=0;int f=0;char ch=getchar();
while(ch<'0'||ch>'9') {f|=(ch=='-');ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return;
}
struct qnode
{
int v,c;
qnode(int _v=0,int _c=0):v(_v),c(_c){}
bool operator < (const qnode &r) const
{
return c>r.c;
}
};
struct node
{
int to,index,w;
}E[M<<3];
int head[M],cnt,n,m;
int dis[M],dist[N][N];
P cw[4][N][N];
int ar[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
bool vis[M];
char mp[N][N];
int s,e;
queue<P>que;
inline int cal(P t)
{
return (t.first-1)*m+t.second;
}
void add(int u,int v,int w)
{
E[++cnt].to=v;
E[cnt].w=w;
E[cnt].index=head[u];
head[u]=cnt;
}
void dji()
{
for(int i=1;i<=n*m;i++)
{
dis[i]=INF;
vis[i]=false;
}
priority_queue<qnode>que;
que.push(qnode(s,0));
dis[s]=0;
while(!que.empty())
{
qnode top=que.top();
que.pop();
int u=top.v;
if(vis[u]) continue;
vis[u]=true;
for(int i=head[u];i;i=E[i].index)
{
int v=E[i].to,cost=E[i].w;
if(!vis[v] && dis[v]>dis[u]+cost)
{
dis[v]=dis[u]+cost;
que.push(qnode(v,dis[v]));
}
}
}
}
void bfs()
{
while(!que.empty())
{
P top=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int ax=top.first+ar[i][0],ay=top.second+ar[i][1];
if(ax>0 && ay>0 && ax<=n && ay<=m && !dist[ax][ay] && mp[ax][ay]=='.')
{
dist[ax][ay]=dist[top.first][top.second]+1;
que.push(P(ax,ay));
}
}
}
}
int main()
{
read(n);read(m);
for(int i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='C')
{
mp[i][j]='.';
s=cal(P(i,j));
}
else if(mp[i][j]=='F')
{
mp[i][j]='.';
e=cal(P(i,j));
}
else if(mp[i][j]=='#') que.push(P(i,j));
}
}
bfs();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='#') continue;
for(int k=0;k<2;k++)
{
int ax=i+ar[k][0],ay=j+ar[k][1];
if(ax>0 && ay>0 && ax<=n && ay<=m)
{
if(mp[ax][ay]=='#') cw[k][i][j]=P(i,j);
else cw[k][i][j]=cw[k][ax][ay];
}
}
}
}
for(int i=n;i>0;i--)
{
for(int j=m;j>0;j--)
{
if(mp[i][j]=='#') continue;
for(int k=2;k<4;k++)
{
int ax=i+ar[k][0],ay=j+ar[k][1];
if(ax>0 && ay>0 && ax<=n && ay<=m)
{
if(mp[ax][ay]=='#') cw[k][i][j]=P(i,j);
else cw[k][i][j]=cw[k][ax][ay];
}
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='#') continue;
for(int k=0;k<4;k++)
{
int ax=i+ar[k][0],ay=j+ar[k][1];
if(k>=2 && ax>0 && ay>0 && ax<=n && ay<=m && mp[ax][ay]=='.')
{
add(cal(P(ax,ay)),cal(P(i,j)),1);
add(cal(P(i,j)),cal(P(ax,ay)),1);
}
if(cw[k][i][j]!=P(i,j)) add(cal(P(i,j)),cal(cw[k][i][j]),dist[i][j]);
}
}
}
dji();
if(dis[e]==INF) puts("no");
else printf("%d\n",dis[e]);
return 0;
}