版权声明:欢迎转载,请注明出处,谢谢 https://blog.csdn.net/Dream_maker_yk/article/details/82693823
LOJ2613 NOIP2013 华容道
这是个好题,具体题意比较麻烦可以直接看LINK中的链接
然后考虑我们可能的移动方式
首先我们需要把白块移动到需要移动块S的附近(附近四格)
然后我们就可以考虑怎么对S进行移动
- 操作一:把S和白块互换位置
- 操作二:把白块从S的一个方向移动到另一方向(方便交换位置)
第一种操作的代价是1很显然,后一种操作我们每次移动的最小代价是可以预处理的
然后我们就可以定义状态 表示S在 且白块在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;
}