NOIP2013华容道 大爆搜

时间:2020-11-30 14:27:47

预处理出每个点周围四个点互相到达的最短路,再在整个图上跑SPFA,要记录路径

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#define N 32
using namespace std;
int dx[]={-,,,},dy[]={,,-,};
int n,m,g[N][N],dis[N][N][][],f[N][N][];
bool bo[N][N],vis[N][N][];
int qx[N*N],qy[N*N],fn[N*N],h,t;
int bfs1(int sx,int sy,int tx,int ty,int xx,int yy){
if(tx==sx&&ty==sy)return ;
memset(bo,,sizeof bo);
qx[]=sx;qy[]=sy;h=t=;bo[sx][sy]=;fn[]=;
bo[xx][yy]=;
while(h<=t){
int nx=qx[h],ny=qy[h++];
for(int i=;i<;i++)
if(g[nx+dx[i]][ny+dy[i]]&&!bo[nx+dx[i]][ny+dy[i]]){
bo[nx+dx[i]][ny+dy[i]]=;
qx[++t]=nx+dx[i];qy[t]=ny+dy[i];
fn[t]=fn[h-]+;
if(nx+dx[i]==tx&&ny+dy[i]==ty)return fn[t];
}
}return dis[][][][];
}
void find(int x,int y){
for(int i=;i<;i++)if(g[x+dx[i]][y+dy[i]]){
dis[x][y][i][i]=;
for(int j=i+;j<;j++)if(g[x+dx[j]][y+dy[j]]){
int d=bfs1(x+dx[i],y+dy[i],x+dx[j],y+dy[j],x,y);
dis[x][y][i][j]=d;
dis[x][y][j][i]=d;
}
}
}
void init(){
memset(dis,0x3f,sizeof dis);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)if(g[i][j])
find(i,j);
} struct data{
int x,y,pos;
}d,ne;
int spfa(int sx,int sy,int tx,int ty){
memset(vis,,sizeof vis);
if(sx==tx&&sy==ty)return ;
queue<data> q; while(!q.empty())q.pop();
for(int i=;i<;i++)if(g[sx+dx[i]][sy+dy[i]]){
vis[sx+dx[i]][sy+dy[i]][i]=;
q.push((data){sx+dx[i],sy+dy[i],i});
}
while(!q.empty()){
d=q.front(); vis[d.x][d.y][d.pos]=; q.pop();
for(int i=;i<;i++){
if(g[d.x+dx[i]][d.y+dy[i]]&&f[d.x+dx[i]][d.y+dy[i]][i]>f[d.x][d.y][d.pos]+dis[d.x][d.y][d.pos^][i]+){
f[d.x+dx[i]][d.y+dy[i]][i]=f[d.x][d.y][d.pos]+dis[d.x][d.y][d.pos^][i]+;
if(!vis[d.x+dx[i]][d.y+dy[i]][i]){
vis[d.x+dx[i]][d.y+dy[i]][i]=;
q.push((data){d.x+dx[i],d.y+dy[i],i});
}
}
}
}
int ans=0x3f3f3f3f;
for(int i=;i<;i++)
ans=min(ans,f[tx][ty][i]);
return ans==0x3f3f3f3f?-:ans;
}
int work(int ex,int ey,int sx,int sy,int tx,int ty){
memset(f,0x3f,sizeof f);
for(int i=;i<;i++)
if(g[sx+dx[i]][sy+dy[i]])
f[sx+dx[i]][sy+dy[i]][i]=bfs1(ex,ey,sx+dx[i],sy+dy[i],sx,sy)+;
return spfa(sx,sy,tx,ty);
} int main(){
int q,ex,ey,sx,sy,tx,ty;
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&g[i][j]);
init();
while(q--){
scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
printf("%d\n",work(ex,ey,sx,sy,tx,ty));
}
return ;
}

Code