Fox And Two Dots

本文介绍了一种算法,用于解决TwoDots游戏中的环路检测问题。通过深度优先搜索(DFS)来检查地图上是否存在由相同颜色的点构成的环路。文章提供了两种实现方法,并附有代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Fox And Two Dots

Time Limit: 2000ms
Memory Limit: 262144KB
This problem will be judged on  CodeForces. Original ID: 510B
64-bit integer IO format: %I64d      Java class name: (Any)
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:

  1. These k dots are different: if i ≠ j then di is different from dj.
  2. k is at least 4.
  3. All dots belong to the same color.
  4. 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.

Input

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

Output "Yes" if there exists a cycle, and "No" otherwise.

 

Sample Input

Input
3 4
AAAA
ABCA
AAAA
Output
Yes
Input
3 4
AAAA
ABCA
AADA
Output
No
Input
4 4
YYYR
BYBY
BBBY
BBBY
Output
Yes
Input
7 6
AAAAAB
ABBBAB
ABAAAB
ABABBB
ABAAAB
ABBBAB
AAAAAB
Output
Yes
Input
2 13
ABCDEFGHIJKLM
NOPQRSTUVWXYZ
Output
No

Hint

In first sample test all 'A' form a cycle.

In second sample there is no such cycle.

The third sample is displayed on the picture above ('Y' = Yellow, 'B' = Blue, 'R' = Red).

 

Source

题意:
  第一行,输入N,M,然后再输入N*M的地图,问你能否在该地图中找到能够构成环的相同字符,如果可以输出Yes,否则输出No。
  一开始,看N,M<=50还以为直接用深搜遍历全部点的可能,找到一个符合请客就可以跳出,而且还标记每次最初的点,这个标记不还原,然后递归中的标记还原,结果,直接超时了。囧囧囧。。。(应该是输入的数据组数很多组,坑爹呀...)
  这样的方法不太可行的,后来想到,弄一个标记数组SIGN[][],对走过的每一个点进行标记SIGN[][]=1,这些标记不需要还原,在递归中遇到相同的字符的话,再去判断该点是否已经被标记过了,如果都符合,则说明能够构成一个环。这样就减少了很多的回溯,复杂度也才N*M。其中还要注意的地方时要防止向反方向搜索,因为我们只对标记数组进行操作,对Map[][]没有任何的改变。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 char Map[55][55];/*地图*/
 6 int MAP[55][55];/*标记走过的点*/
 7 int Len_X,Len_Y;
 8 int SIGN;/*SING=1表示没有找到结果,SIGN=0表示找到环*/
 9 void DFS(int x,int y,char str,int N)/*深度搜索,str为最初字符,N表示方向*/
10 {
11 
12     if(!SIGN)return;/*如果找到一个条件,结束搜索*/
13     if(Map[x][y]==str)/*判断如果当前字符一样*/
14     {
15         if(MAP[x][y]==1)/*字符一样且搜索过说明构成了环*/
16             {SIGN=0;return;}
17         else            /*否则,继续进行循环*/
18         {
19             MAP[x][y]=1;    /*标记该点已经走过*/
20             if(N!=0)DFS(x-1,y,str,1);    /*防止反方向搜索*/
21             if(N!=1)DFS(x+1,y,str,0);    /*防止反方向搜索*/
22             if(N!=2)DFS(x,y-1,str,3);    /*防止反方向搜索*/
23             if(N!=3)DFS(x,y+1,str,2);    /*防止反方向搜索*/
24         }
25     }
26 }
27 
28 int main()
29 {
30     int N,M;
31     int i,j;
32     char str;
33     while(scanf("%d%d",&Len_X,&Len_Y)!=EOF)
34     {
35         memset(Map,'*',sizeof(Map));/*地图初始化,建围墙*/
36         memset(MAP,-1,sizeof(MAP)); /*标记数组初始化,建围墙*/
37         for(i=1;i<=Len_X;i++)
38         {
39             scanf(" %s",Map[i]+1);/*输入地图*/
40             Map[i][Len_Y+1]='*';/*处理最后一个字符\n*/
41         }
42         for(i=1,SIGN=1;i<=Len_X&&SIGN;i++)
43         {
44             for(j=1;j<=Len_Y&&SIGN;j++)
45             {
46                 if(MAP[i][j]==-1)/*如果该数组没有被标记过,从该点进行查找*/
47                 {
48                     MAP[i][j]=1;    /*标记该点已经使用过*/
49                     DFS(i+1,j,Map[i][j],0);/*向下搜索*/
50                     DFS(i-1,j,Map[i][j],1);/*向上搜索*/
51                     DFS(i,j+1,Map[i][j],2);/*向右搜索*/
52                     DFS(i,j-1,Map[i][j],3);/*向左搜索*/
53                 }
54             }
55         }
56         if(!SIGN)printf("Yes\n");
57         else printf("No\n");
58     }
59     return 0;
60 }
View Code

 修改:2015.5.8

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 using namespace std;
 5 int Len_X,Len_Y,SIGN;
 6 char Map[100][100];
 7 int Map_S[100][100];
 8 void DFS(int x,int y,char  Str,int N)/*N用来控制方向*/
 9 {
10     if(SIGN==1)return ;
11     if(Map_S[x][y]==1)/*如果该点走过,且和原本相同则说明构成环*/
12     {
13         if(Map[x][y]==Str)SIGN=1;
14         return ;
15     }
16     if(Map[x][y]==Str)/**/
17     {
18         Map_S[x][y]=1;/*标记该点走过*/
19         if(N!=1)DFS(x+1,y,Str,0);/*防止方向搜索*/
20         if(N!=0)DFS(x-1,y,Str,1);/*防止方向搜索*/
21         if(N!=3)DFS(x,y+1,Str,2);/*防止方向搜索*/
22         if(N!=2)DFS(x,y-1,Str,3);/*防止方向搜索*/
23     }
24     return ;
25 }
26 
27 int main()
28 {
29     int Begin_x,Begin_y,i,j,k,A,B;
30     while(scanf("%d%d",&Len_X,&Len_Y)!=EOF)
31     {
32         for(i=0;i<=Len_X+1;i++)
33         {
34             for(j=0;j<=Len_Y+1;j++)
35             {
36                 if(i==0||j==0||i==Len_X+1||j==Len_Y+1)
37                 {Map_S[i][j]=1;Map[i][j]='*';}
38                 else
39                 {
40                     scanf(" %c",&Map[i][j]);
41                     Map_S[i][j]=0;
42                 }
43 
44             }
45         }
46         
47         for(i=1,SIGN=0;i<=Len_X;i++)
48         {
49             for(j=1;j<=Len_Y;j++)
50             {
51                 for(k=0;k<4;k++) /*判断四个方向*/
52                 {
53                      if(Map_S[i][j]==0)/*判断改点是否已经走过*/
54                      DFS(i,j,Map[i][j],k);
55                 }
56             }
57         }
58         if(SIGN)printf("Yes\n");
59         else printf("No\n");
60     }
61     return 0;
62 }
View Code

 

 

转载于:https://www.cnblogs.com/Wurq/articles/4461650.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值