题目:https://www.luogu.org/problemnew/show/P1363
题意:
有一个地图,起点是S,障碍物用#表示。可以将这个地图不断的在四周重复,问从起点开始是否可以走到无限远的地方去。
思路:
刚开始想的是地图放中间,然后在四周都拼一个同样的,然后看看能不能走回到起点。
但是发现仅仅是拼四个是不够的,那拼九个?反正又是MLE又是WA的。
主要思路还是dfs搜索,题目中其实给了提示了,可以利用取模。
把每一次走的位置都压缩到一个地图上去。但是又去标记这是在那一块被访问到的。
如果可以两次走到这个点(其实并不是走到这个点而是走到另一块的对应位置)就说明可以走到无限远的地方。
所以我们需要个vis数组。第一个用来标记这个点是否被访问过,第二三个用来标记访问到对应这个点时候的横纵坐标。
dfs时即需要知道当前的坐标,又需要知道取模之前实际的坐标。
如果之前走到这个点时候的横纵坐标和现在实际的坐标是相同的,说明走到的是同一个点,如果有一个是不同的说明已经走到另一块地图上去了。
1 //#include<bits/stdc++> 2 #include<stdio.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstring> 6 #include<stdlib.h> 7 #include<queue> 8 #include<map> 9 #include<stack> 10 #include<set> 11 12 #define LL long long 13 #define ull unsigned long long 14 #define inf 0x7f7f7f7f 15 16 using namespace std; 17 18 int n, m; 19 const int maxn = 1505; 20 char gra[maxn][maxn]; 21 int vis[maxn][maxn][3]; 22 int dx[4] = {0, 0, -1, 1}; 23 int dy[4] = {1, -1, 0, 0}; 24 int stx, sty; 25 26 bool check(int x, int y) 27 { 28 if(x < 0 || y < 0 || x >= n || y >= m)return false; 29 else return true; 30 } 31 32 bool ans; 33 void dfs(int x, int y, int acx, int acy) 34 { 35 if(vis[x][y][0] && vis[x][y][1] == acx && vis[x][y][2] == acy){ 36 37 return; 38 } 39 else if(vis[x][y][0] && (vis[x][y][1] != acx || vis[x][y][2] != acy)){ 40 ans = true; 41 return; 42 } 43 vis[x][y][0] = true; 44 vis[x][y][1] = acx; 45 vis[x][y][2] = acy; 46 for(int i = 0; i < 4; i++){ 47 int tox = (x + dx[i] + n) % n, toy = (y + dy[i] + m) % m; 48 if(check(tox, toy) && gra[tox][toy] != '#'){ 49 dfs(tox, toy, acx + dx[i], acy + dy[i]); 50 } 51 } 52 return; 53 } 54 55 int main() 56 { 57 while(scanf("%d%d", &n, &m) != EOF){ 58 memset(gra, 0, sizeof(gra)); 59 memset(vis, 0, sizeof(vis)); 60 ans = false; 61 for(int i = 0; i < n; i++){ 62 cin>>gra[i]; 63 for(int j = 0; j < m; j++){ 64 if(gra[i][j] == 'S'){ 65 stx = i; 66 sty = j; 67 } 68 } 69 } 70 71 dfs(stx, sty, stx, sty);//vis[stx][sty][0] = true; 72 if(ans)printf("Yes "); 73 else printf("No "); 74 } 75 76 return 0; 77 }