/*
学习李大牛每天复习之前写过的算法,每天找一题出来做做复习;
*****并查集篇******
*/
这还算是一道简单的并查集,思路在代码中:
15MS | 340K |
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#define x m*(i-1)+j
//define 实际上是字符替换,利用这一点将题中本应该是m*(i-1)+j的地方替换为x
//使得程序简洁
using namespace std;
char map[53][53];
struct squares
{
bool u;
bool d;
bool l;
bool r;
}s[11]; //存放 A-K 的田里渠道的方向
int f[3000];
int find(int a) //查找 父亲函数
{
if(f[a]==a) return a;
else
return f[a] = find(f[a]);
}
void set() //按题目所给图 初始化 A-K 田里渠道的方向。未置为true的默认false
{
s[0].u = s[0].l = s[1].u = s[1].r
= s[2].l = s[2].d = s[3].d = s[3].r
= s[4].u = s[4].d = s[5].l = s[5].r
= s[6].l = s[6].r = s[6].u = s[7].u
= s[7].l = s[7].d = s[8].l = s[8].r
= s[8].d = s[9].u = s[9].d = s[9].r
= s[10].u = s[10].d = s[10].l = s[10].r = true;
}
int main()
{
set();
int n,m;
while(scanf("%d%d",&n,&m))
{
if(n==-1&&m==-1)
break;
for(int i = 1; i <= n; i++)
{
cin.get();
for(int j = 1; j <= m; j++)
{
scanf("%c",&map[i][j]);
f[x] = x;
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(s[map[i][j]-'A'].r==1&&s[map[i][j+1]-'A'].l==1)//向右方向查找
{
int f1 = find(f[x+1]);
int f2 = find(f[x]);
if(j!=m&&f2!=f1)
{
f[f1] = f[f2];
}
}
if(s[map[i][j]-'A'].d==1&&s[map[i+1][j]-'A'].u==1)//向下方向查找
{
int f1 = find(f[x+m]);
int f2 = find(f[x]);
if(i!=n&&f2!=f1)
{
f[f1] = f[f2];
}
}
}
}
int ans = 0;
for(int i = 1; i <= n; i++) //该点的父亲为自己,则说明这是某一片区的父节点 ans++
{
for(int j = 1; j <= m; j++)
{
if(find(x) == x)
ans++;
}
}
printf("%d\n",ans);
}
}