NOIP2013華容道 大爆搜

預處理出每個點周圍四個點互相到達的最短路,再在整個圖上跑SPFA,要記錄路徑

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章