LOJ2613 NOIP2013 华容道
这是个好题,具体题意比较麻烦可以直接看LINK中的链接
然后考虑我们可能的移动方式
首先我们需要把白块移动到需要移动块S的附近(附近四格)
然后我们就可以考虑怎么对S进行移动
- 操作一:把S和白块互换位置
- 操作二:把白块从S的一个方向移动到另一方向(方便交换位置)
第一种操作的代价是1很显然,后一种操作我们每次移动的最小代价是可以预处理的
然后我们就可以定义状态x,y,dir表示S在(x,y)且白块在S的dir方向上
我们就只需要考虑在状态之间进行转移,用spfa就够了
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 40 4 #define INF 0x3f3f3f3f 5 int mx[4]={0,0,1,-1}; 6 int my[4]={1,-1,0,0}; 7 int mv[N][N][4][4]; 8 int dp[N][N][4]; 9 bool inq[N][N][4]; 10 int g[N][N],dis[N][N]; 11 int n,m,q; 12 int ex,ey,sx,sy,tx,ty; 13 struct Node1{int x,y;}; 14 struct Node2{int x,y,dir;}; 15 bool check_in(int x,int y){return (x>0&&x<=n&&y>0&&y<=m)&&g[x][y];} 16 void bfs1(int x,int y,int dir){ 17 if(!check_in(x+mx[dir],y+my[dir]))return; 18 static queue<Node1> q; 19 memset(dis,0x3f,sizeof(dis)); 20 dis[x][y]=-1; 21 dis[x+mx[dir]][y+my[dir]]=0; 22 q.push((Node1){x+mx[dir],y+my[dir]}); 23 while(!q.empty()){ 24 Node1 now=q.front();q.pop(); 25 for(int i=0;i<4;i++){ 26 int nx=now.x+mx[i]; 27 int ny=now.y+my[i]; 28 if(!check_in(nx,ny))continue; 29 if(dis[nx][ny]>dis[now.x][now.y]+1){ 30 dis[nx][ny]=dis[now.x][now.y]+1; 31 q.push((Node1){nx,ny}); 32 } 33 } 34 } 35 for(int i=0;i<4;i++){ 36 int nx=x+mx[i]; 37 int ny=y+my[i]; 38 if(check_in(nx,ny))mv[x][y][dir][i]=dis[nx][ny]; 39 } 40 } 41 void bfs2(){ 42 memset(dis,0x3f,sizeof(dis)); 43 static queue<Node1> q; 44 dis[ex][ey]=0; 45 dis[sx][sy]=-1; 46 q.push((Node1){ex,ey}); 47 while(!q.empty()){ 48 Node1 now=q.front();q.pop(); 49 for(int i=0;i<4;i++){ 50 int nx=now.x+mx[i]; 51 int ny=now.y+my[i]; 52 if(!check_in(nx,ny))continue; 53 if(dis[nx][ny]>dis[now.x][now.y]+1){ 54 dis[nx][ny]=dis[now.x][now.y]+1; 55 q.push((Node1){nx,ny}); 56 } 57 } 58 } 59 } 60 #define NOW now.x][now.y][now.dir 61 int spfa(){ 62 memset(dp,0x3f,sizeof(dp)); 63 memset(inq,0,sizeof(inq)); 64 static queue<Node2> nq; 65 for(int i=0;i<4;i++){ 66 int nx=sx+mx[i]; 67 int ny=sy+my[i]; 68 if((!check_in(nx,ny))||dis[sx+mx[i]][sy+my[i]]==INF)continue; 69 dp[sx][sy][i]=dis[sx+mx[i]][sy+my[i]]; 70 nq.push((Node2){sx,sy,i}); 71 inq[sx][sy][i]=1; 72 } 73 while(!nq.empty()){ 74 Node2 now=nq.front();nq.pop(); 75 inq[NOW]=0; 76 for(int i=0;i<4;i++) 77 if(dp[now.x][now.y][i]>dp[NOW]+mv[NOW][i]){ 78 dp[now.x][now.y][i]=dp[NOW]+mv[NOW][i]; 79 if(!inq[now.x][now.y][i]){ 80 inq[now.x][now.y][i]=1; 81 nq.push((Node2){now.x,now.y,i}); 82 } 83 } 84 int nx=now.x+mx[now.dir]; 85 int ny=now.y+my[now.dir]; 86 if(dp[nx][ny][now.dir^1]>dp[NOW]+1){ 87 dp[nx][ny][now.dir^1]=dp[NOW]+1; 88 if(!inq[nx][ny][now.dir^1]){ 89 inq[nx][ny][now.dir^1]=1; 90 nq.push((Node2){nx,ny,now.dir^1}); 91 } 92 } 93 } 94 int ans=INF; 95 for(int i=0;i<4;i++)ans=min(ans,dp[tx][ty][i]); 96 if(ans==INF)ans=-1; 97 return ans; 98 } 99 int main(){ 100 memset(mv,0x3f,sizeof(mv)); 101 scanf("%d%d%d",&n,&m,&q); 102 for(int i=1;i<=n;i++) 103 for(int j=1;j<=m;j++)scanf("%d",&g[i][j]); 104 for(int i=1;i<=n;i++) 105 for(int j=1;j<=m;j++)if(g[i][j]) 106 for(int k=0;k<4;k++)bfs1(i,j,k); 107 while(q--){ 108 scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty); 109 bfs2(); 110 if(sx==tx&&sy==ty)printf("0 "); 111 else printf("%d ",spfa()); 112 } 113 return 0; 114 }