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 }
View Code

 

posted @ 2017-11-07 10:50  鲸头鹳  阅读(219)  评论(0编辑  收藏  举报