1. 程式人生 > >luogu1979 華容道 (dijkstra+bfs)

luogu1979 華容道 (dijkstra+bfs)

code 過程 front can 華容道 lse fine tor while

我想動某個點的話,一定要先把空白點移動到這個點旁邊,然後調換這個點和空白點,一直重復

那麽,我們就可以記一些狀態(x,y,s) (s={0,1},{0,-1},{1,0},{-1,0}),表示我要動的點在(x,y),然後空白點在(x+s.x,y+s.y)

這樣的話我們就可以建圖:$(x,y,s)-1->(x+s.x,y+s.y,s^{-1})$ (s^{-1}表示一個相反的方向,比如如果s是右邊的話,那它就是左邊)

$(x,y,s)-C(x,y,s+s.x,y+s.y,x+i.x,y+i.y)->(x,y,i)$ 其中,C(a,b,c,d,e,f)表示我目前這個點在(a,b),空白點在(c,d),要把空白點挪到(e,f)的最小步數,而且挪的過程中不能經過(a,b)(要不然會把要動的那個點換走)

這樣的話,就可以一邊bfs算出C的值,一邊跑最短路了。

然而復雜度$O(q*(mn)^2)$,過不去。

考慮預處理出C,直接做顯然不行($mn^3$),但其實我們要用到C的情況,都是空白點在要處理的點的旁邊的,那它就可以壓縮成(x,y,s,tx,ty),是900*4*900的。

當然,一開始我們的空白點和要做的點並沒有在一起,只要再單獨bfs一下,先把空白點挪到它邊上就可以了。

要註意有起始點和目標點相同的情況,要判掉。

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define pa2 pair<int,Node>
 4
#define ll long long 5 using namespace std; 6 const int maxn=33; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<0||c>9){if(c==-) neg=-1;c=getchar();} 11 while(c>=0&&c<=9) x=x*10+c-0,c=getchar(); 12 return x*neg; 13 } 14 15 struct
Node{ 16 int x,y,s; 17 Node (int x1,int x2,int x3){x=x1,y=x2,s=x3;} 18 }; 19 int f[maxn][maxn],N,M,Q,dis[maxn][maxn][4][maxn][maxn],dis2[maxn][maxn][4]; 20 int step[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; 21 bool can[maxn][maxn],flag[maxn][maxn],flag2[maxn][maxn][4]; 22 queue<pa > q; 23 priority_queue<pa2,vector<pa2>,greater<pa2> > q2; 24 25 bool operator < (Node a,Node b){return a.x<b.x;} 26 27 int bfs1(int a,int b,int c,int x0,int y0){ 28 memset(flag,0,sizeof(flag)); 29 while(!q.empty()) q.pop();q.push(make_pair(x0,y0)); 30 dis[a][b][c][x0][y0]=0; 31 while(!q.empty()){ 32 int x=q.front().first,y=q.front().second;q.pop(); 33 for(int i=0;i<=3;i++){ 34 int xx=x+step[i][0],yy=y+step[i][1]; 35 if(!flag[xx][yy]&&can[xx][yy]){ 36 q.push(make_pair(xx,yy)); 37 dis[a][b][c][xx][yy]=dis[a][b][c][x][y]+1; 38 } 39 }flag[x][y]=1; 40 } 41 } 42 43 int dijkstra(int ex,int ey,int sx,int sy,int tx,int ty){ 44 if(sx==tx&&sy==ty) return 0; 45 memset(dis2,-1,sizeof(dis2));memset(flag2,0,sizeof(flag2)); 46 while(!q2.empty()) q2.pop(); 47 can[sx][sy]=0;memset(dis[0][0][0],-1,sizeof(dis[0][0][0])); 48 bfs1(0,0,0,ex,ey); 49 for(int i=0;i<=3;i++){ 50 int xx=sx+step[i][0],yy=sy+step[i][1]; 51 if(dis[0][0][0][xx][yy]!=-1){ 52 dis2[xx][yy][i^1]=dis[0][0][0][xx][yy]+1; 53 q2.push(make_pair(dis2[xx][yy][i^1],Node(xx,yy,i^1))); 54 } 55 }can[sx][sy]=1; 56 while(!q2.empty()){ 57 Node p=q2.top().second;q2.pop();if(flag2[p.x][p.y][p.s]) continue; 58 for(int i=0;i<=3;i++){ 59 int xx=p.x+step[i][0],yy=p.y+step[i][1]; 60 if(dis[p.x][p.y][p.s][xx][yy]!=-1){ 61 if(dis2[xx][yy][i^1]==-1||dis2[xx][yy][i^1]>dis[p.x][p.y][p.s][xx][yy]+dis2[p.x][p.y][p.s]+1){ 62 dis2[xx][yy][i^1]=dis[p.x][p.y][p.s][xx][yy]+dis2[p.x][p.y][p.s]+1; 63 q2.push(make_pair(dis2[xx][yy][i^1],Node(xx,yy,i^1))); 64 } 65 } 66 }flag2[p.x][p.y][p.s]=1; 67 }int re=-1; 68 for(int i=0;i<=3;i++){ 69 if(dis2[tx][ty][i]==-1) continue; 70 if(re==-1) re=dis2[tx][ty][i]; 71 else re=min(re,dis2[tx][ty][i]); 72 }return re; 73 } 74 75 int main(){ 76 int i,j,k; 77 N=rd(),M=rd();Q=rd(); 78 for(i=1;i<=N;i++){ 79 for(j=1;j<=M;j++) can[i][j]=rd(); 80 } 81 memset(dis,-1,sizeof(dis)); 82 for(i=1;i<=N;i++){ 83 for(j=1;j<=M;j++){ 84 if(!can[i][j]) continue;can[i][j]=0; 85 for(k=0;k<=3;k++){ 86 int ii=i+step[k][0],jj=j+step[k][1]; 87 if(can[ii][jj]) bfs1(i,j,k,ii,jj); 88 }can[i][j]=1; 89 } 90 } 91 for(i=1;i<=Q;i++){ 92 int x1=rd(),x2=rd(),x3=rd(),x4=rd(),x5=rd(),x6=rd(); 93 printf("%d\n",dijkstra(x1,x2,x3,x4,x5,x6)); 94 } 95 return 0; 96 }

luogu1979 華容道 (dijkstra+bfs)