JZYZOJ1442 [noip2013]华容道 bfs 最短路 剪枝
http://172.20.6.3/Problem_Show.asp?id=1442
想到最短路的简直神了,如果我写我大概只能写一个30分的bfs。
从数据范围可以看出思路是bfs剪枝,但这里的剪枝是通过最短路的预处理实现的。
设需要移动的格子为a格子。
对求最小移动数有意义的移动只有两种,一种是空白格子的移动,一种是a格子移动到空白格子里。
可以得知要把空白格子移动到a格子旁边然后对a格子进行移动。
那么我们有了每次查找时进行的预处理1:求空白格子到a格子四周格子的最短路。
在模拟移动的过程中,可以发现a格子移动的方向是由其旁边的空白格子的位置决定的,对改变a格子移动方向有意义的步数是改变空白格子相对于a格子的方向的步数。
所以我们就有了预处理2:在查找前预处理出loc[x][y][i][j],即空白格子从格子(x,y)的i方向移动到j方向的最短路。
需要注意的是,预处理1中求最短路是不能经过a格子所在位置的,同样,其他的bfs或最短路处理也要注意格子移动对所求格子位置的改变,避免改变所求格子位置的情况。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const long long modn=1000000007; 9 int n,m,d; 10 int e[40][40]={}; 11 int dis[40][40]={}; 12 int an[40][40][4]={}; 13 int loc[40][40][4][4]={}; 14 int vis[40][40][4]={}; 15 int d1[4]={0,0,1,-1}; 16 int d2[4]={1,-1,0,0}; 17 int ex,ey,sx,sy,tx,ty,ma; 18 struct pa{ 19 int x; 20 int y,w; 21 }; 22 void getit(int xx,int yy){ 23 int x,y; 24 queue<pa>q; 25 pa z; 26 for(int i=0;i<4;i++){ 27 z.x=xx+d1[i]; 28 z.y=yy+d2[i]; 29 memset(dis,63,sizeof(dis)); 30 if(e[z.x][z.y]){ 31 dis[z.x][z.y]=0; 32 q.push(z); 33 } 34 while(!q.empty()){ 35 x=q.front().x;y=q.front().y;q.pop(); 36 for(int i=0;i<4;i++){ 37 z.x=x+d1[i]; 38 z.y=y+d2[i]; 39 if(e[z.x][z.y]&&(z.x!=xx||z.y!=yy)&&dis[z.x][z.y]==ma){ 40 dis[z.x][z.y]=dis[x][y]+1; 41 q.push(z); 42 } 43 } 44 } 45 for(int j=0;j<4;j++){ 46 int xx1,yy1; 47 xx1=xx+d1[j]; 48 yy1=yy+d2[j]; 49 loc[xx][yy][i][j]=dis[xx1][yy1]; 50 } 51 } 52 } 53 void pre(){ 54 pa z; 55 queue<pa>q; 56 memset(dis,63,sizeof(dis)); 57 dis[ex][ey]=0; 58 z.x=ex; 59 z.y=ey; 60 q.push(z); 61 int x,y; 62 while(!q.empty()){ 63 x=q.front().x;y=q.front().y;q.pop(); 64 for(int i=0;i<4;i++){ 65 z.x=x+d1[i]; 66 z.y=y+d2[i]; 67 if(e[z.x][z.y]&&(z.x!=sx||z.y!=sy)&&dis[z.x][z.y]==ma){ 68 dis[z.x][z.y]=dis[x][y]+1; 69 q.push(z); 70 } 71 } 72 } 73 } 74 int bfs(){ 75 if(sx==tx&&sy==ty)return 0; 76 pre(); 77 queue<pa>q;pa z; 78 memset(an,63,sizeof(an)); 79 for(int i=0;i<4;i++){ 80 z.x=sx+d1[i]; 81 z.y=sy+d2[i]; 82 z.w=i; 83 if(e[z.x][z.y]&&dis[z.x][z.y]!=ma){ 84 an[sx][sy][i]=dis[z.x][z.y]; 85 z.x=sx;z.y=sy; 86 vis[sx][sy][i]=1; 87 q.push(z); 88 } 89 }int x,y,w; 90 while(!q.empty()){ 91 x=q.front().x; 92 y=q.front().y; 93 w=q.front().w; 94 q.pop(); 95 for(int i=0;i<4;i++){ 96 if(i==w)continue; 97 z.x=x;z.y=y;z.w=i; 98 if(e[x+d1[w]][y+d2[w]]&&an[x][y][w]+loc[x][y][w][i]<an[x][y][i]){ 99 an[x][y][i]=an[x][y][w]+loc[x][y][w][i]; 100 if(!vis[x][y][i]){ 101 vis[x][y][i]=1; 102 q.push(z); 103 } 104 } 105 } 106 z.x=x+d1[w];z.y=y+d2[w]; 107 if(w==0)z.w=1; 108 else if(w==1)z.w=0; 109 else if(w==2)z.w=3; 110 else z.w=2; 111 if(an[x][y][w]+1<an[z.x][z.y][z.w]){ 112 an[z.x][z.y][z.w]=an[x][y][w]+1; 113 if(!vis[z.x][z.y][z.w]){ 114 vis[z.x][z.y][z.w]=1; 115 q.push(z); 116 } 117 } 118 vis[x][y][w]=0; 119 } 120 int ans=ma; 121 for(int i=0;i<4;i++){ 122 ans=min(ans,an[tx][ty][i]); 123 } 124 if(ans!=ma)return ans; 125 return -1; 126 } 127 int main(){ 128 //freopen("wtf.in","r",stdin); 129 scanf("%d%d%d",&n,&m,&d); 130 for(int i=1;i<=n;i++){ 131 for(int j=1;j<=m;j++){ 132 scanf("%d",&e[i][j]); 133 } 134 }memset(loc,63,sizeof(loc)); 135 ma=loc[1][1][1][1]; 136 for(int i=1;i<=n;i++){ 137 for(int j=1;j<=m;j++){ 138 getit(i,j); 139 } 140 } 141 for(int i=1;i<=d;i++){ 142 scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty); 143 memset(vis,0,sizeof(vis)); 144 printf("%d\n",bfs()); 145 } 146 return 0; 147 }