看了题目感觉bfs好像可以做,但是因为有传送门这个条件又觉得bfs太麻烦了。
同时传送门又很像一条特殊的边,看了看限制,n,m只有300,那就直接建图跑一下最短路就好了。
建图方法:
1.对于每个不为#的点,对于它的上下左右4个点,只要另一个点也不为#,那么建一条边权为1有向边。
2.对于传送门,如果两个点都不为#,那么建一条边权为3的有向边。
然后dijkstra一下就好了,spfa应该也可以吧,不过spfa经常会被卡,所以还是dijkstra稳健。
BFS也是可以做的,只需要用map标记一下传送门,在BFS的时候判断一下就行。(太麻烦了还是最短路好)
代码:
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<vector> #include<cstring> #include<queue> #define fs first #define se second #define pb push_back #define cppio ios::sync_with_stdio(false);cin.tie(0) using namespace std; typedef long long ll; typedef pair<int,int> pii; typedef vector<int> VI; const int maxn=1e5+6; const ll inf=0x3f3f3f3f; const ll mod=1e9+7; const int dx[]={1,-1,0,0}; const int dy[]={0,0,1,-1}; int top = 0; int head[maxn]; char mp[310][310]; struct Edge{ int to,w,next; }edge[maxn*4]; void init(){ top=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w){ edge[top].w=w; edge[top].to=v; edge[top].next=head[u]; head[u]=top++; } struct Node{ int id;ll val; Node(int id,ll val):id(id),val(val){ } bool operator <(const Node &bb) const { return val > bb.val; } }; ll dis[maxn]; int vis[maxn]; void dijk(int st){ for(int i=0;i<maxn;i++){ dis[i]=1e18; } memset(vis,0,sizeof(vis)); priority_queue<Node> q; dis[st]=0; q.push(Node(st,0)); while(!q.empty()){ int u=q.top().id; q.pop(); if(vis[u]) continue; vis[u]=1; for (int i = head[u]; i != -1; i = edge[i].next) { int to=edge[i].to;int w=edge[i].w; if(dis[to]>dis[u]+w&&!vis[to]){ dis[to]=dis[u]+w; q.push(Node(to,dis[to])); } } } } int main(){ int n,m,k; while(~scanf("%d%d%d",&n,&m,&k)){ init(); for(int i=1;i<=n;i++){ scanf("%s",mp[i]+1); } int stx=0,sty=0; int tx=0,ty=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(mp[i][j]=='S'){ stx=i;sty=j; } if(mp[i][j]=='T'){ tx=i;ty=j; } for(int z=0;z<4;z++){ int xx=i+dx[z];int yy=j+dy[z]; if(xx<1||xx>n||yy<1||yy>m||mp[i][j]=='#'||mp[xx][yy]=='#') continue; int num1=i*m+j;int num2=xx*m+yy; addedge(num1,num2,1); } } } for(int i=1;i<=k;i++){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1++;y1++;x2++;y2++; if(mp[x1][y1]=='#'||mp[x2][y2]=='#') continue; int num1=x1*m+y1;int num2=x2*m+y2; addedge(num1,num2,3); } dijk(stx*m+sty); if(vis[tx*m+ty]==0) printf("-1\n"); else printf("%lld\n",dis[tx*m+ty]); } return 0; }