UVA - 1601 - The Morning after Halloween

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的主要内容,如果未能解决你的问题,请参考以下文章

UVa1601 The Morning after Halloween(双向bfs)

The Morning after Halloween uva1601

UVA - 1601 - The Morning after Halloween

UVa1601 The Morning after Halloween (双向广度优先搜索)

UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)

UVA10596 Morning Walk欧拉回路