CF Fox And Two Dots (DFS)
Fox Ciel is playing a mobile puzzle game called "Two Dots". The basic levels are played on a board of size n × m cells, like this:
Each cell contains a dot that has some color. We will use different uppercase Latin characters to express different colors.
The key of this game is to find a cycle that contain dots of same color. Consider 4 blue dots on the picture forming a circle as an example. Formally, we call a sequence of dots d1, d2, ..., dk a cycle if and only if it meets the following condition:
- These k dots are different: if i ≠ j then di is different from dj.
- k is at least 4.
- All dots belong to the same color.
- For all 1 ≤ i ≤ k - 1: di and di + 1 are adjacent. Also, dk and d1 should also be adjacent. Cells x and y are called adjacent if they share an edge.
Determine if there exists a cycle on the field.
The first line contains two integers n and m (2 ≤ n, m ≤ 50): the number of rows and columns of the board.
Then n lines follow, each line contains a string consisting of m characters, expressing colors of dots in each line. Each character is an uppercase Latin letter.
Output "Yes" if there exists a cycle, and "No" otherwise.
3 4
AAAA
ABCA
AAAA
Yes
3 4
AAAA
ABCA
AADA
No
4 4
YYYR
BYBY
BBBY
BBBY
Yes
7 6
AAAAAB
ABBBAB
ABAAAB
ABABBB
ABAAAB
ABBBAB
AAAAAB
Yes
2 13
ABCDEFGHIJKLM
NOPQRSTUVWXYZ
No
读错题了,一直以为是要找矩形,比赛快结束才被队友提醒。
DFS一下就可以,每个点记录一下它是从起点出发的第几个点,如果搜索的过程中遇到了走过的点,那么判断一下这两个点的差是否大于等于3,如果满足就说明形成了一个环。本来想的是,如果从某个点出发没找到,那么就说明和这个点连通的所有点都不可行,于是加入了一个剪枝,将这一连通分量减掉,但是似乎没什么作用,加和不加都是15ms,网上还有一种更炫的写法,就是把起点放在当前点的屁股后面,如果遇到了走过的点就找到,我有空试试,写出来的话就更新上来。
---------------------------------------------------------------------------------------------------------
深夜补发,刚才说的那个算法写了下,实际效果没想象的那么好,还没有我之前写的那个快,不过仔细想想,复杂度貌似是一样的。
不加剪枝:
#include <bits/stdc++.h> using namespace std; const int UPDATE[][2] = {{0,1},{0,-1},{1,0},{-1,0}}; char MAP[55][55]; int N,M; struct Node { bool vis = 0; int n = 0; }VIS[55][55]; bool dfs(int,int,int,char); int main(void) { cin >> N >> M; for(int i = 1;i <= N;i ++) cin >> MAP[i] + 1; for(int i = 1;i <= N;i ++) for(int j = 1;j <= M;j ++) { VIS[i][j].vis = VIS[i][j].n = 1; if(dfs(i,j,1,MAP[i][j])) { puts("Yes"); return 0; } VIS[i][j].vis = VIS[i][j].n = 0; } puts("No"); return 0; } bool dfs(int x,int y,int sum,char color) { for(int i = 0;i < 4;i ++) { int new_x = x + UPDATE[i][0]; int new_y = y + UPDATE[i][1]; if(new_x > N || new_x < 1 || new_y > M || new_y < 1 || MAP[new_x][new_y] != color) continue; if(VIS[new_x][new_y].vis && sum - VIS[new_x][new_y].n + 1 >= 4) return true; if(VIS[new_x][new_y].vis) continue; VIS[new_x][new_y].vis = true; VIS[new_x][new_y].n = sum + 1; if(dfs(new_x,new_y,sum + 1,color)) return true; VIS[new_x][new_y].vis = false; VIS[new_x][new_y].n = sum; } return false; }
加了剪枝:
#include <bits/stdc++.h> using namespace std; const int UPDATE[][2] = {{0,1},{0,-1},{1,0},{-1,0}}; char MAP[55][55]; int N,M; struct Node { bool vis = 0; int n = 0; }VIS[55][55]; bool dfs(int,int,int,char); void cut(int,int,char); int main(void) { cin >> N >> M; for(int i = 1;i <= N;i ++) cin >> MAP[i] + 1; for(int i = 1;i <= N;i ++) for(int j = 1;j <= M;j ++) { if(MAP[i][j] == '.') continue; VIS[i][j].vis = VIS[i][j].n = 1; if(dfs(i,j,1,MAP[i][j])) { puts("Yes"); return 0; } VIS[i][j].vis = VIS[i][j].n = 0; cut(i,j,MAP[i][j]); } puts("No"); return 0; } bool dfs(int x,int y,int sum,char color) { for(int i = 0;i < 4;i ++) { int new_x = x + UPDATE[i][0]; int new_y = y + UPDATE[i][1]; if(new_x > N || new_x < 1 || new_y > M || new_y < 1 || MAP[new_x][new_y] != color) continue; if(VIS[new_x][new_y].vis && sum - VIS[new_x][new_y].n + 1 >= 4) return true; if(VIS[new_x][new_y].vis) continue; VIS[new_x][new_y].vis = true; VIS[new_x][new_y].n = sum + 1; if(dfs(new_x,new_y,sum + 1,color)) return true; VIS[new_x][new_y].vis = false; VIS[new_x][new_y].n = sum; } return false; } void cut(int x,int y,char cor) { for(int i = 0;i < 4;i ++) { int new_x = x + UPDATE[i][0]; int new_y = y + UPDATE[i][1]; if(new_x > N || new_x < 1 || new_y > M || new_y < 1 || MAP[new_x][new_y] != cor || VIS[new_x][new_y].vis) continue; MAP[new_x][new_y] = '.'; cut(new_x,new_y,cor); } }
网上的算法:
#include <bits/stdc++.h> using namespace std; const int UPDATE[][2] = {{0,1},{0,-1},{1,0},{-1,0}}; int N,M; char MAP[55][55]; bool VIS[55][55]; int BACK_X,BACK_Y; bool dfs(int i,int j,char color); int main(void) { cin >> N >> M; for(int i = 1;i <= N;i ++) cin >> MAP[i] + 1; for(int i = 1;i <= N;i ++) for(int j = 1;j <= M;j ++) { VIS[i][j] = 1; if(dfs(i,j,MAP[i][j])) { puts("Yes"); return 0; } VIS[i][j] = 0; } puts("No"); return 0; } bool dfs(int i,int j,char color) { int back_x = BACK_X; int back_y = BACK_Y; for(int k = 0;k < 4;k ++) { int next_x = i + UPDATE[k][0]; int next_y = j + UPDATE[k][1]; if(next_x > N || next_x < 1 || next_y > M || next_y < 1 || MAP[next_x][next_y] != color) continue; if(VIS[next_x][next_y] && next_x != BACK_X && next_y != BACK_Y) { return true; } if(VIS[next_x][next_y]) continue; BACK_X = i; BACK_Y = j; VIS[next_x][next_y] = 1; if(dfs(next_x,next_y,color)) return true; VIS[next_x][next_y] = 0; BACK_X = back_x; BACK_Y = back_y; } return false; }