BFS+SPFA-NOIP2013 Huarong Road

luoguP1979

It's hard to think about the idea. At the beginning, I thought that SPFA should be pretreated at every point, but it would be very troublesome, and there would be problems

Because empty lattices are different in different directions of each point, we consider abstracting the state into points and storing them in a three-dimensional array

id[i][j][k] indicates that the space is in the K direction of (i,j)

We can deal with the number of steps between States, which can be done with bfs

Connect the sides between the States. Set a start state and end state each time you ask, and connect them to the transferable state respectively

See the code for details

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define maxn 35
#define M 810005
#define inf 0x3f3f3f3f
using namespace std;
int n,m,t,a[maxn][maxn],cnt,head[M],dis[maxn][maxn][5][5];
int id[maxn][maxn][5],tot,d[maxn][maxn],ans[M];
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
bool vis[M];

inline int rd(){
	int x=0,f=1;char c=' ';
	while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();}
	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
	return x*f;
}

struct EDGE{
	int to,nxt,w;
}edge[M<<1];

inline void add(int x,int y,int z){
	edge[++cnt].to=y; edge[cnt].nxt=head[x]; head[x]=cnt; edge[cnt].w=z;
}

inline bool judge(int x,int y){
	return (x>0 && x<=n && y>0 && y<=m);
}
queue< pair<int,int> > q;
inline int bfs(int x1,int y1,int x2,int y2){
	if(x1==x2 && y1==y2) return 0;//Minimum steps from x1,y1 to x2,y2 
	while(!q.empty()) q.pop();
	memset(d,0,sizeof d);
	q.push(make_pair(x1,y1));
	while(!q.empty()){
		int x=q.front().first,y=q.front().second; q.pop();
		for(int i=0;i<4;i++){
			int nx=x+dx[i],ny=y+dy[i];
			if(!judge(nx,ny) || !a[nx][ny] || d[nx][ny]) continue;
			d[nx][ny]=d[x][y]+1;
			if(nx==x2 && ny==y2) return d[nx][ny];
			q.push(make_pair(nx,ny));
		}
	}
	return inf;
}

inline void prework(){
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int k=0;k<4;k++)
				id[i][j][k]=++tot;
	memset(dis,0x3f,sizeof dis);
	for(int i=1;i<=n;i++)//Preprocessing (i,j), the minimum number of steps required for a space to move from its k direction to its t direction 
		for(int j=1;j<=m;j++)
			if(a[i][j]){
				a[i][j]=0;
				for(int k=0;k<4;k++){
					int x=i+dx[k],y=j+dy[k];
					if(!judge(x,y) || !a[x][y]) continue;
					for(int t=0;t<4;t++){
						int nx=i+dx[t],ny=j+dy[t];
						if(!judge(nx,ny) || !a[nx][ny]) continue;
						dis[i][j][k][t]=bfs(x,y,nx,ny)+1;
					}
				}
				a[i][j]=1;
			}//(i,j) the number of steps to move a lattice in k direction, and the state is reversed 
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int k=0;k<4;k++)
				for(int t=0;t<4;t++)
					if(dis[i][j][k][t]<inf)
						add(id[i][j][k],id[i+dx[t]][j+dy[t]][t^1],dis[i][j][k][t]);
	return; 
}
queue<int> Q;
inline int SPFA(int s,int t){
	memset(ans,0x3f,sizeof ans); memset(vis,0,sizeof vis);
	while(!Q.empty()) Q.pop();
	Q.push(s); vis[s]=1; ans[s]=0;
	while(!Q.empty()){
		int u=Q.front(); Q.pop();
		for(int i=head[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			if(ans[v]>ans[u]+edge[i].w){
				ans[v]=ans[u]+edge[i].w;
				if(!vis[v]) vis[v]=1,Q.push(v);
			}
		} vis[u]=0;
	}
	return ans[t]<inf?ans[t]:-1;
}


int main(){
	n=rd(); m=rd(); t=rd();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			a[i][j]=rd();
	prework();
	while(t--){
		int ex=rd(),ey=rd(),sx=rd(),sy=rd(),tx=rd(),ty=rd();
		if(!a[sx][sy] || !a[tx][ty] || !a[ex][ey]) {puts("-1");continue;}
		if(sx==tx && sy==ty) {puts("0");continue;}
		int S=++tot,T=++tot;
		a[sx][sy]=0;
		for(int i=0;i<4;i++){
			int x=sx+dx[i],y=sy+dy[i];
			if(a[x][y] && judge(x,y)){
				int tmp=bfs(ex,ey,x,y);//Empty grid around the starting point 
				if(tmp<inf) add(S,id[sx][sy][i],tmp);
			}
		}
		a[sx][sy]=1;
		for(int i=0;i<4;i++){
			int x=tx+dx[i],y=ty+dy[i];
			if(a[x][y] && judge(x,y))
				add(id[tx][ty][i],T,0); 
		}
		printf("%d\n",SPFA(S,T));
	}
	return 0;
} 

 

Posted by xdracox on Wed, 25 Dec 2019 09:23:02 -0800