nod-1416-两点

题目

福克斯在玩一款手机解迷游戏,这个游戏叫做”两点”。基础级别的时候是在一个n×m单元上玩的。像这样:




 

每一个单元有包含一个有色点。我们将用不同的大写字母来表示不同的颜色。

这个游戏的关键是要找出一个包含同一颜色的环。看上图中4个蓝点,形成了一个环。一般的,我们将一个序列 d1,d2,...,dk 看成一个环,当且仅当它符合下列条件时:

1.    这k个点不一样,即当 i≠j时, di  dj不同。

2.    k至少是4。

3.    所有的点是同一种颜色。

4.    对于所有的 1≤i≤k-1: di  di+1 是相邻的。还有 dk  d1 也应该相邻。单元 x 和单元 y 是相邻的当且仅当他们有公共边。

当给出一幅格点时,请确定里面是否有环。


Input
单组测试数据。
第一行包含两个整数n和m (2≤n,m≤50):板子的行和列。
接下来n行,每行包含一个有m个字母的串,表示当前行每一个点的颜色。每一个字母都是大写字母。
Output
如果有环输出Yes,否则输出No。
Input示例
3 4
AAAA
ABCA
AAAA
3 4
AAAA
ABCA
AADA
Output示例
Yes
No

思路:

           这道题目搞了我好久,虽然感觉简单但是不知道是自己最近弱逼了还是怎么了,写了好久;
          开始深搜,后来广搜,发现思路都错了,想着是计数,记录扩展到每个节点的cnt,然后如果当前减去下一个已经发现的大于4就认为ok,没想到这明显是有漏洞的,至少广搜搞不定;

        
        后来重整思路,其实很简单,无论深搜还是广搜,只要点扩展时不要扩展自己的父节点就行,然后一旦碰到已经找过的点肯定是有环的;换种说法,其实就是找环,如何找,也就是先标记已经找到的,如果下次发现扩展的是之前找到的就证明有环;只要防止一种情况,就是从1,1 找到2,1,当2,1扩展时还会扩展1,1,这个时候直接过滤掉就行,不要走老路;

         哎,好久不练就是生疏,今天bfs搞定,改天再dfs写一遍吧!


太乱了

代码:

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
using namespace std;
typedef struct NODE
{
   int pos_x;
   int pos_y;
   int pre_x;
   int pre_y;
   NODE(int x, int y, int px, int py):pos_x(x),pos_y(y), pre_x(px), pre_y(py)
   {
       
   }
}Node;
queue<Node> q;
char arr[55][55];
int flag[55][55];
bool judge_pos(int i, int j, int x, int y, int p_x,int p_y, int n, int m)
{
   if (x >= 1 && x <= n && y >= 1 && y <= m && arr[i][j] == arr[x][y] &&( x!=p_x || y!= p_y))
   {
      if (flag[x][y])
      {
           return true;
      }
      else
      {
           flag[x][y] = true;
           Node new_node(x,y,i,j);
           q.push(new_node);
      }
   }
   return false;
}
bool solve(int n, int m)
{
   while(!q.empty())
   {
       Node tmp = q.front();
       q.pop();
       int x = tmp.pos_x;
       int y = tmp.pos_y;
       int p_x = tmp.pre_x;
       int p_y = tmp.pre_y;
       if (judge_pos(x,y,x-1,y,p_x, p_y, n,m) ||
          judge_pos(x,y,x+1,y,p_x, p_y,n,m)||
          judge_pos(x,y,x,y-1,p_x, p_y,n,m)||
          judge_pos(x,y,x,y+1,p_x, p_y,n,m))
          {
              return true;
          }
   }
   return false;
}
int main()
{
   int n, m;
   while (scanf("%d %d", &n, &m)!=EOF)
   {
       getchar();
       memset(flag, 0, sizeof(flag));
       for (int i = 1; i <= n; ++ i)
       {
           for (int j = 1; j <= m; ++ j)
           {
               scanf("%c", &arr[i][j]);
           }
           getchar();
       }
       bool exit_flag = false;
       for (int i = 1; i <= n && !exit_flag; ++ i)
       {
           for (int j = 1; j <= m && !exit_flag; ++ j)
           {
               if (!flag[i][j])
               {
                   while(!q.empty())
                       q.pop();
                   
                   Node node(i,j,0,0);
                   q.push(node);
                   if (solve(n,m))
                   {
                       exit_flag = true;
                       printf("Yes\n");
                   }
               }
           }
       }
       if (!exit_flag)
            printf("No\n");
   }
   return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值