看了题目感觉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;
}


京公网安备 11010502036488号