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 }
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 }
以上是关于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 && 降维 && 状压)