传送门
这是一道坑点极其多的BFS题,难度倒是还好,就是可能好多细节处理不好就会一直wa心态咋咧,这道题就是在原有bfs的基础上加上一个传送门,传送门大家如果练习过bfs专题的话应该不会陌生吧,但是这题存在多个传送门而且可以互相传送,那么我们就考虑有可能传送到障碍物上或者回到原点形成一个传送环,这种情况就直接退出就好啦,实现对于起点如果是传送门进行处理,还有就是对于传送的时候是不计算路程的,d[nx][ny]=d[ex][ey],但是考虑到传送门的不确定性,我们如果传送到一个之前的走过的位置,假如当前位置的路程比前一个路程的小,那么我们就不需要更新啦,因而我是这么写的:d[nx][ny]=min(d[ex][ey],d[nx][ny]) ,大致思路就是这样,具体实现参考代码:
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int N=1005;
int ddx[4]={-1,1,0,0};
int ddy[4]={0,0,1,-1};
int nx[N],ny[N];
char mp[N][N];
int tp[N][N];
int d[N][N];
bool vis[N][N];
int n,m;
struct node{
int x,y;
};
void bfs()
{
queue<node>q;
int sx=1,sy=1;
while(q.size())q.pop();
d[1][1]=0;
while(tp[sx][sy])
{
int num=tp[sx][sy];
sx=nx[num];
sy=ny[num];
d[sx][sy]=0;
if(sx==1&&sy==1)return;
if(mp[sx][sy]=='*')return;
}
node now;
now.x=sx;now.y=sy;
q.push(now);
while(q.size())
{
node cur=q.front();
q.pop();
vis[cur.x][cur.y]=1;
for(int i=0;i<4;i++)
{
int dx=cur.x+ddx[i];
int dy=cur.y+ddy[i];
if(dx>0&&dy>0&&dx<=n&&dy<=m&&mp[dx][dy]=='.'&&!vis[dx][dy]&&d[dx][dy]>d[cur.x][cur.y]+1)
{
int ex=dx,ey=dy;
d[dx][dy]=d[cur.x][cur.y]+1;
int flag=0;
while(tp[ex][ey])
{
int k=tp[ex][ey];
ex=nx[k];
ey=ny[k];
if(mp[ex][ey]=='*')break;
if(ex==dx&&ey==dy)break;
d[ex][ey]=min(d[dx][dy],d[ex][ey]);
}
q.push(node{ex,ey});
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin >> mp[i][j];
}
}
int p;
scanf("%d",&p);
int index=1;
while(p--)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
nx[index]=c;ny[index]=d;
tp[a][b]=index++;
//这里是用来存储传送门的下一地点
}
int x,y;
scanf("%d%d",&x,&y);
memset(d,INF,sizeof(d));
bfs();
if(d[x][y]==INF)cout << "No solution" << endl;
else cout << d[x][y] << endl;
}