标签:not string include 思路 pre could cin next pac
3 5 6 XXXXXX XZ..ZX XXXXXX M.G... ...... 5 6 XXXXXX XZZ..X XXXXXX M..... ..G... 10 10 .......... ..X....... ..M.X...X. X......... .X..X.X.X. .........X ..XX....X. X....G...X ...ZX.X... ...Z..X..X
1 1 -1
题意就是给你一个迷宫,不对,就是说你现在被困在迷宫里,要去和你GF见面,但是迷宫中还有人不可以走的墙和会杀死人的幽灵,幽灵每个单位时间都会往上下左右延申新的幽灵。
幽灵有两个,M是你的位置,G是GF的位置。
幽灵每秒可以延申两格,你可以每秒走三步,GF每秒只能走一步,如果在不被杀死的情况和女朋友汇合就输出最小单位时间,否则输出-1.
(注意幽灵是可以往墙上延申的)
因为两个人都可以动,不用说,双向BFS是肯定的,不过有一点就是,如何实现每秒走三步以及判断是否被杀死呢?
答案是我也不知道。这道题目就留给各位自己思考。
=7=嘻嘻 不闹了。其实可以换个思路去思考,我们可以用三个bfs代替走三步,但是如何判断是否被杀死呢,其实这道题可以不需要判断是否被杀死,而是判断人物走到能否在幽灵延申到某个位置之前走到那个位置,用曼哈顿距离判断就行了。
提一下什么是曼哈顿距离
常用距离度量方法有十一种,而我们大部分时间只用到欧氏距离和曼哈顿距离。
设两个点的坐标(X1,Y1),(X2,Y2);
欧氏距离就是坐标的直线距离 = sqrt((X2 - X1)2+(Y2 - Y1)2)
而曼哈顿距离就是以欧式距离为斜边构造直角三角形的两直角边和 = |X2 - X1| + |Y2 - Y1|
为什么有这么多构造方式以及其区别,这篇博文就不详细介绍了。
值得一题的是,因为是双向搜索,所以需要开两个二维数组或是一个三维数组分别标记你或者GF是否走过。
还有就是代码BFS中的
1 int len = q[w].size(); 2 while(len--)
因为我们不是一次就搜索完,我们的BFS仅仅只是做走一步的作用,所以只把当前已经存的点的下一点存入就行了。若是觉得难以理解可以替换成while(!q[w].empty)观察每一步的输出情况。
代码:
1 #include <iostream> 2 #include <string> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <sstream> 6 #include <iomanip> 7 #include <map> 8 #include <stack> 9 #include <deque> 10 #include <queue> 11 #include <vector> 12 #include <set> 13 #include <list> 14 #include <cstring> 15 #include <cctype> 16 #include <algorithm> 17 #include <iterator> 18 #include <cmath> 19 #include <bitset> 20 #include <ctime> 21 #include <fstream> 22 #include <limits.h> 23 #include <numeric> 24 25 using namespace std; 26 27 #define F first 28 #define S second 29 #define mian main 30 #define ture true 31 32 #define MAXN 1000000+5 33 #define MOD 1000000007 34 #define PI (acos(-1.0)) 35 #define EPS 1e-6 36 #define MMT(s) memset(s, 0, sizeof s) 37 typedef unsigned long long ull; 38 typedef long long ll; 39 typedef double db; 40 typedef long double ldb; 41 typedef stringstream sstm; 42 const int INF = 0x3f3f3f3f; 43 44 int fx[4][2]={1,0,-1,0,0,1,0,-1}; 45 char mp[810][810]; 46 int vis[2][810][810]; 47 int gx,gy,mx,my,n,m,step; //记录坐标,这里的step指的是GF走的步数,应该理解成走了多少单位时间 48 pair<int,int>cur,z[2]; //z用来记录幽灵位置 49 queue<pair<int,int> >q[2]; //分别记录你和GF的路径 50 51 bool check(pair<int,int> x){ 52 if(x.F < 0 || x.S < 0 || x.F >= n || x.S >= m || mp[x.F][x.S] == ‘X‘) 53 return false; 54 if((abs(x.F-z[0].F)+abs(x.S-z[0].S)) <= 2*step || (abs(x.F-z[1].F)+abs(x.S-z[1].S)) <= 2*step) //判断在幽灵延申到某个点之前是否能走到 55 return false; 56 return true; 57 } 58 59 int bfs(int w){ 60 pair<int,int>tp,next; 61 int len = q[w].size(); 62 while(len--){ //注意这里不是搜完,因为是多次搜索,只需要把当前步骤行进完就行了 63 tp = q[w].front(); 64 q[w].pop(); 65 if(!check(tp)) continue; 66 for(int i = 0; i < 4; i++){ 67 next.F = tp.F + fx[i][0]; 68 next.S = tp.S + fx[i][1]; 69 if(!check(next)) 70 continue; 71 if(!vis[w][next.F][next.S]){ 72 if(vis[1-w][next.F][next.S]) //判断下一个点是否对方已经走过 73 return 1; 74 vis[w][next.F][next.S] = 1; 75 q[w].push(next); 76 } 77 } 78 } 79 return 0; 80 } 81 82 int solve(){ 83 while(!q[0].empty()) 84 q[0].pop(); 85 while(!q[1].empty()) 86 q[1].pop(); 87 88 cur.F = mx; 89 cur.S = my; 90 q[0].push(cur); 91 cur.F = gx; 92 cur.S = gy; 93 q[1].push(cur); 94 MMT(vis); 95 vis[0][mx][my] = vis[1][gx][gy] = 1; 96 step = 0; 97 98 while((!q[0].empty()) || (!q[1].empty())){ 99 step++; 100 if(bfs(0)) //通过三次bfs达到走三步 101 return step; 102 if(bfs(0)) 103 return step; 104 if(bfs(0)) 105 return step; 106 if(bfs(1)) 107 return step; 108 } 109 return -1; 110 } 111 112 int main(){ 113 ios_base::sync_with_stdio(false); 114 cout.tie(0); 115 cin.tie(0); 116 int t; 117 cin>>t; 118 while(t--){ 119 int cnt = 0; 120 cin>>n>>m; 121 for(int i = 0; i < n; i++) 122 cin>>mp[i]; 123 for(int i = 0; i < n; i++) 124 for(int j = 0; j < m; j++){ 125 if(mp[i][j] == ‘G‘) 126 gx = i, gy = j; 127 if(mp[i][j] == ‘M‘) 128 mx = i, my = j; 129 if(mp[i][j] == ‘Z‘) 130 z[cnt].F = i, z[cnt++].S = j; 131 } 132 cout << solve() << endl; 133 } 134 return 0; 135 }
标签:not string include 思路 pre could cin next pac
原文地址:https://www.cnblogs.com/xenny/p/9387961.html