题解:电网的传送迷宫
BuQiuRu4587 · · 题解
暴力做法是直接建出分层图,然后 01bfs,复杂度是
首先,由于第
那么,我们可以新建节点
预处理完
所以总复杂度就是
代码如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int opt,n,m,p,q;
int id(int x,int y){return (x-1)*m+y;}
char ch[1005*1005];
struct edge{
int from,to;
}e[1005*1005*10];int head[1005*1005],siz;
void addedge(int x,int y){
e[++siz].to=y;
e[siz].from=head[x],head[x]=siz;
}
int b[1005*1005],f[1005*1005],dis1[1005*1005],dis2[1005*1005];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>opt>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>ch[id(i,j)];
dis1[id(i,j)]=dis2[id(i,j)]=1e15;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(ch[id(i,j)]=='#') continue;
if(i-1>=1&&ch[id(i-1,j)]!='#') addedge(id(i,j),id(i-1,j));
if(i+1<=n&&ch[id(i+1,j)]!='#') addedge(id(i,j),id(i+1,j));
if(j-1>=1&&ch[id(i,j-1)]!='#') addedge(id(i,j),id(i,j-1));
if(j+1<=m&&ch[id(i,j+1)]!='#') addedge(id(i,j),id(i,j+1));
}
}
int sx,sy,fir,tx,ty,ed=0;
cin>>sx>>sy;fir=id(sx,sy);
cin>>p>>q;
if(opt==1) cin>>tx>>ty,ed=id(tx,ty);
queue<int> Q;
for(int i=1;i<=p;i++){
int x,y;cin>>x>>y;
Q.push(id(x,y));
dis1[id(x,y)]=0;
}
for(int i=1;i<=q;i++){
f[i]=1e15;
int x,y;cin>>x>>y;
b[i]=id(x,y);
}
b[0]=fir;
while(!Q.empty()){
int now=Q.front();Q.pop();
for(int i=head[now];i;i=e[i].from){
int u=e[i].to;
if(dis1[u]>dis1[now]+1){
dis1[u]=dis1[now]+1;
Q.push(u);
}
}
}
for(int i=1;i<=q;i++){
if(dis1[b[i-1]]>=1e15) continue;
f[i]=f[i-1]+dis1[b[i-1]];
}
Q.push(b[0]);
int pos=1;
dis2[b[0]]=0;
while(!Q.empty()){
int now=Q.front();Q.pop();
for(int i=head[now];i;i=e[i].from){
int u=e[i].to;
if(dis2[u]>dis2[now]+1){
dis2[u]=dis2[now]+1;
Q.push(u);
}
}
while(pos<=q&&(Q.empty()||f[pos]<=dis2[Q.front()]+1)){
Q.push(b[pos]);
dis2[b[pos]]=min(dis2[b[pos]],f[pos]);
pos++;
}
}
if(opt){
if(dis2[ed]>=1e15) cout<<-1;
else cout<<dis2[ed];
return 0;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(dis2[id(i,j)]>=1e15) cout<<-1<<' ';
else cout<<dis2[id(i,j)]<<' ';
}cout<<'\n';
}
}