首页 > 代码库 > UVA - 1601 - The Morning after Halloween

UVA - 1601 - The Morning after Halloween

题目链接:点击这里

题目大意:

给出一个迷宫,在迷宫中有用小写字母表示的几个精灵,

有用大写字母表示的对应精灵的目标位置。

问最少需要进行多少次移动可以到达目标位置。

题目分析:

这道题有两种做法。

第一种做法,优化后的BFS搜索。

首先我们先通过给出的迷宫,提取出空格(即可走的路径),

建立新的图,用邻接表把新的图保存下来,这样就不用判断每个移动点是否

是空格位置还是‘#’位置。然后根据这个邻接表,进行BFS搜索。

还有两点值得注意

1.是当前位置的储存,可以通过二进制的方法将三个点的位置ID保存在一个数里面,需要的时候再进行解码。

2.将每个点的位置用ID保存下来,直接通过ID查取对应坐标(即代码所用的邻接表)。

第二种做法,双向BFS搜索。

双向BFS适用于目标位置和起始位置固定的搜索。

改搜索可以有效的降低实际复杂度。

不过需要注意的是,每次搜索需要以层位单位进行搜索,一次将相同深度的状态枚举干净。

给出代码:

技术分享
  1 #include <iostream>  2 #include <cstdio>  3 #include <cstring>  4 #include <vector>  5 #include <string>  6 #include <queue>  7 #include <algorithm>  8 using namespace std;  9 inline int getID(int a,int b,int c) 10 { 11     return (a<<16)|(b<<8)|c; 12 } 13 inline bool confict(int a1,int b1,int a2,int b2) 14 { 15     return ((a2==b2)||(a1==b2&&b1==a2)); 16 } 17 int dis[210][210][210]; 18 int dx[] = {0, -1, 1, 0, 0}; 19 int dy[] = {0, 0, 0, -1, 1}; 20 int  deg[210]; 21 int  to[210][210]; 22 int st[5]; 23 int ed[5]; 24 char s[20][20]; 25 int w,h,n; 26 int bfs() 27 { 28     queue<int> q; 29     q.push(getID(st[0], st[1], st[2])); 30     dis[st[0]][st[1]][st[2]] = 0; 31     while(!q.empty()) 32     { 33         int u=q.front(); 34         q.pop(); 35         int a = (u >> 16) & 0xff, b = (u >> 8) & 0xff, c = u & 0xff; 36       //  cout<<a<<" "<<b<<" "<<c<<endl; 37         if(a==ed[0]&&b==ed[1]&&c==ed[2]) 38             return dis[a][b][c]; 39         for(int i=0;i<deg[a];i++) 40         { 41             int a1=to[a][i]; 42             for(int j=0;j<deg[b];j++) 43             { 44                 int b1=to[b][j]; 45                 if(confict(a,b,a1,b1)) 46                     continue; 47                 for(int k=0;k<deg[c];k++) 48                 { 49                  //   cout<<i<<" "<<j<<" "<<k<<" *"<<endl; 50                     int c1=to[c][k]; 51                     if(confict(a,c,a1,c1)||confict(b,c,b1,c1)) 52                         continue; 53                     if(dis[a1][b1][c1]==-1) 54                     { 55                         q.push(getID(a1,b1,c1)); 56                         dis[a1][b1][c1]=dis[a][b][c]+1; 57                     } 58                 } 59             } 60         } 61     } 62     return -1; 63 } 64 int main() 65 { 66     while(~scanf("%d%d%d\n",&w,&h,&n)&&n) 67     { 68       for(int i = 0; i < h; i++) 69       { 70           fgets(s[i], 20, stdin); 71          // cout<<i<<endl; 72       } 73         int cnt=0,x[210],y[210],id[21][21]; 74         for(int i=0;i<h;i++) 75             for(int j=0;j<w;j++) 76             if(!(s[i][j]==#)) 77         { 78             x[cnt]=i; 79             y[cnt]=j; 80             id[i][j]=cnt; 81             if(islower(s[i][j])) 82                 st[s[i][j]-a]=cnt; 83             else if(isupper(s[i][j])) 84                 ed[s[i][j]-A]=cnt; 85             cnt++; 86         } 87         for(int i=0;i<cnt;i++) 88         { 89             deg[i]=0; 90             for(int j=0;j<5;j++) 91             { 92                 int nx=x[i]+dx[j]; 93                 int ny=y[i]+dy[j]; 94                 if(!(s[nx][ny]==#)) 95                 { 96                     to[i][deg[i]++]=id[nx][ny]; 97                 } 98             } 99         }100         if(n <= 2)  { deg[cnt] = 1; to[cnt][0] = cnt;    st[2] = ed[2] = cnt++; }101         if(n <= 1)  { deg[cnt] = 1; to[cnt][0] = cnt;    st[1] = ed[1] = cnt++; }102         memset(dis,-1,sizeof(dis));103         printf("%d\n",bfs());104     }105     return 0;106 }
优化BFS
技术分享
  1 #include <iostream>  2 #include <cstdio>  3 #include <cstring>  4 #include <vector>  5 #include <string>  6 #include <queue>  7 #include <algorithm>  8 using namespace std;  9 inline int getID(int a,int b,int c) 10 { 11     return (a<<16)|(b<<8)|c; 12 } 13 inline bool confict(int a1,int b1,int a2,int b2) 14 { 15     return ((a2==b2)||(a1==b2&&b1==a2)); 16 } 17 int dis[210][210][210]; 18 int mark[210][210][210]; 19 int dx[] = {0, -1, 1, 0, 0}; 20 int dy[] = {0, 0, 0, -1, 1}; 21 int  deg[210]; 22 int  to[210][210]; 23 int st[5]; 24 int ed[5]; 25 char s[20][20]; 26 int w,h,n; 27 int bfs() 28 { 29     queue<int> q1; 30     queue<int> q2; 31     q1.push(getID(st[0], st[1], st[2])); 32     q2.push(getID(ed[0], ed[1], ed[2])); 33     dis[st[0]][st[1]][st[2]] = 0; 34     dis[ed[0]][ed[1]][ed[2]] = 1; 35     mark[st[0]][st[1]][st[2]]=1; 36     mark[ed[0]][ed[1]][ed[2]]=2; 37     while(!q1.empty()||q2.empty()) 38     { 39         int t1=q1.size(); 40         int t2=q2.size(); 41         while(t1--) 42         { 43             int u=q1.front(); 44             q1.pop(); 45             int a = (u >> 16) & 0xff, b = (u >> 8) & 0xff, c = u & 0xff; 46             //  cout<<a<<" "<<b<<" "<<c<<endl; 47             //if(a==ed[0]&&b==ed[1]&&c==ed[2]) 48             //     return dis[a][b][c]; 49             for(int i=0; i<deg[a]; i++) 50             { 51                 int a1=to[a][i]; 52                 for(int j=0; j<deg[b]; j++) 53                 { 54                     int b1=to[b][j]; 55                     if(confict(a,b,a1,b1)) 56                         continue; 57                     for(int k=0; k<deg[c]; k++) 58                     { 59                         //   cout<<i<<" "<<j<<" "<<k<<" *"<<endl; 60                         int c1=to[c][k]; 61                         if(confict(a,c,a1,c1)||confict(b,c,b1,c1)) 62                             continue; 63                         if(mark[a1][b1][c1]==0) 64                         { 65                             q1.push(getID(a1,b1,c1)); 66                             dis[a1][b1][c1]=dis[a][b][c]+1; 67                             mark[a1][b1][c1]=1; 68                         } 69                         else if(mark[a1][b1][c1]==2) 70                         { 71                             return dis[a][b][c]+dis[a1][b1][c1]; 72                         } 73                     } 74                 } 75             } 76         } 77         while(t2--) 78         { 79             int u=q2.front(); 80             q2.pop(); 81             int a = (u >> 16) & 0xff, b = (u >> 8) & 0xff, c = u & 0xff; 82             //  cout<<a<<" "<<b<<" "<<c<<endl; 83             //if(a==ed[0]&&b==ed[1]&&c==ed[2]) 84             //     return dis[a][b][c]; 85             for(int i=0; i<deg[a]; i++) 86             { 87                 int a1=to[a][i]; 88                 for(int j=0; j<deg[b]; j++) 89                 { 90                     int b1=to[b][j]; 91                     if(confict(a,b,a1,b1)) 92                         continue; 93                     for(int k=0; k<deg[c]; k++) 94                     { 95                         //   cout<<i<<" "<<j<<" "<<k<<" *"<<endl; 96                         int c1=to[c][k]; 97                         if(confict(a,c,a1,c1)||confict(b,c,b1,c1)) 98                             continue; 99                         if(mark[a1][b1][c1]==0)100                         {101                             q2.push(getID(a1,b1,c1));102                             dis[a1][b1][c1]=dis[a][b][c]+1;103                             mark[a1][b1][c1]=2;104                         }105                         else if(mark[a1][b1][c1]==1)106                         {107                             return dis[a][b][c]+dis[a1][b1][c1];108                         }109                     }110                 }111             }112         }113     }114     return -1;115 }116 int main()117 {118     while(~scanf("%d%d%d\n",&w,&h,&n)&&n)119     {120         for(int i = 0; i < h; i++)121         {122             fgets(s[i], 20, stdin);123             // cout<<i<<endl;124         }125         int cnt=0,x[210],y[210],id[21][21];126         for(int i=0; i<h; i++)127             for(int j=0; j<w; j++)128                 if(!(s[i][j]==#))129                 {130                     x[cnt]=i;131                     y[cnt]=j;132                     id[i][j]=cnt;133                     if(islower(s[i][j]))134                         st[s[i][j]-a]=cnt;135                     else if(isupper(s[i][j]))136                         ed[s[i][j]-A]=cnt;137                     cnt++;138                 }139         for(int i=0; i<cnt; i++)140         {141             deg[i]=0;142             for(int j=0; j<5; j++)143             {144                 int nx=x[i]+dx[j];145                 int ny=y[i]+dy[j];146                 if(!(s[nx][ny]==#))147                 {148                     to[i][deg[i]++]=id[nx][ny];149                 }150             }151         }152         if(n <= 2)153         {154             deg[cnt] = 1;155             to[cnt][0] = cnt;156             st[2] = ed[2] = cnt++;157         }158         if(n <= 1)159         {160             deg[cnt] = 1;161             to[cnt][0] = cnt;162             st[1] = ed[1] = cnt++;163         }164         memset(dis,0,sizeof(dis));165         memset(mark,0,sizeof(mark));166         printf("%d\n",bfs());167     }168     return 0;169 }
双向BFS

 

UVA - 1601 - The Morning after Halloween