LOJ2613 NOIP2013 华容道 【最短路】*

版权声明:欢迎转载,请注明出处,谢谢 https://blog.csdn.net/Dream_maker_yk/article/details/82693823

LOJ2613 NOIP2013 华容道


LINK


这是个好题,具体题意比较麻烦可以直接看LINK中的链接


然后考虑我们可能的移动方式

首先我们需要把白块移动到需要移动块S的附近(附近四格)

然后我们就可以考虑怎么对S进行移动

  • 操作一:把S和白块互换位置
  • 操作二:把白块从S的一个方向移动到另一方向(方便交换位置)

第一种操作的代价是1很显然,后一种操作我们每次移动的最小代价是可以预处理的

然后我们就可以定义状态 x , y , d i r x,y,dir 表示S在 ( x , y ) (x,y) 且白块在S的dir方向上

我们就只需要考虑在状态之间进行转移,用spfa就够了


#include<bits/stdc++.h>
using namespace std;
#define N 40
#define INF 0x3f3f3f3f
int mx[4]={0,0,1,-1};
int my[4]={1,-1,0,0};
int mv[N][N][4][4];
int dp[N][N][4];
bool inq[N][N][4];
int g[N][N],dis[N][N];
int n,m,q;
int ex,ey,sx,sy,tx,ty;
struct Node1{int x,y;};
struct Node2{int x,y,dir;};
bool check_in(int x,int y){return (x>0&&x<=n&&y>0&&y<=m)&&g[x][y];}
void bfs1(int x,int y,int dir){
	if(!check_in(x+mx[dir],y+my[dir]))return;
	static queue<Node1> q;
	memset(dis,0x3f,sizeof(dis));
	dis[x][y]=-1;
	dis[x+mx[dir]][y+my[dir]]=0;
	q.push((Node1){x+mx[dir],y+my[dir]});
	while(!q.empty()){
		Node1 now=q.front();q.pop();
		for(int i=0;i<4;i++){
			int nx=now.x+mx[i];
			int ny=now.y+my[i];
			if(!check_in(nx,ny))continue;
			if(dis[nx][ny]>dis[now.x][now.y]+1){
				dis[nx][ny]=dis[now.x][now.y]+1;
				q.push((Node1){nx,ny});
			}
		}
	}
	for(int i=0;i<4;i++){
		int nx=x+mx[i];
		int ny=y+my[i];
		if(check_in(nx,ny))mv[x][y][dir][i]=dis[nx][ny];
	}
}
void bfs2(){
	memset(dis,0x3f,sizeof(dis));
	static queue<Node1> q;
	dis[ex][ey]=0;
	dis[sx][sy]=-1;
	q.push((Node1){ex,ey});
	while(!q.empty()){
		Node1 now=q.front();q.pop();
		for(int i=0;i<4;i++){
			int nx=now.x+mx[i];
			int ny=now.y+my[i];
			if(!check_in(nx,ny))continue;
			if(dis[nx][ny]>dis[now.x][now.y]+1){
				dis[nx][ny]=dis[now.x][now.y]+1;
				q.push((Node1){nx,ny});
			}
		}
	}
}
#define NOW now.x][now.y][now.dir
int spfa(){
	memset(dp,0x3f,sizeof(dp));
	memset(inq,0,sizeof(inq));
	static queue<Node2> nq;
	for(int i=0;i<4;i++){
		int nx=sx+mx[i];
		int ny=sy+my[i];
		if((!check_in(nx,ny))||dis[sx+mx[i]][sy+my[i]]==INF)continue;
		dp[sx][sy][i]=dis[sx+mx[i]][sy+my[i]];
		nq.push((Node2){sx,sy,i});
		inq[sx][sy][i]=1;
	}
	while(!nq.empty()){
		Node2 now=nq.front();nq.pop();
		inq[NOW]=0;
		for(int i=0;i<4;i++)
			if(dp[now.x][now.y][i]>dp[NOW]+mv[NOW][i]){
				dp[now.x][now.y][i]=dp[NOW]+mv[NOW][i];
				if(!inq[now.x][now.y][i]){
					inq[now.x][now.y][i]=1;
					nq.push((Node2){now.x,now.y,i});
				}
			}
		int nx=now.x+mx[now.dir];
		int ny=now.y+my[now.dir];
		if(dp[nx][ny][now.dir^1]>dp[NOW]+1){
			dp[nx][ny][now.dir^1]=dp[NOW]+1;
			if(!inq[nx][ny][now.dir^1]){
				inq[nx][ny][now.dir^1]=1;
				nq.push((Node2){nx,ny,now.dir^1});
			}
		}
	}
	int ans=INF;
	for(int i=0;i<4;i++)ans=min(ans,dp[tx][ty][i]);
	if(ans==INF)ans=-1;
	return ans;
}
int main(){
	memset(mv,0x3f,sizeof(mv));
	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]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)if(g[i][j])
			for(int k=0;k<4;k++)bfs1(i,j,k);
	while(q--){
		scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
		bfs2();
		if(sx==tx&&sy==ty)printf("0\n");
		else printf("%d\n",spfa());
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Dream_maker_yk/article/details/82693823
今日推荐