思路
- 题意
- 给我们一个n*m的农田,每块小块农田的的地下,都有一个如上图所示的水管,某块小农田可以与相邻的小农田连通,如果这两个小农田的 管道可以拼接到一起,问我们 这个图中的 “连通块” 有几个
- 分析
- 这一题 可以用 dfs去递归搜索连通块的数量、也可以用bfs去搜索,最后统计一下dfs、bfs调用的次数就是答案;也可以用并查集 不断合并集合,最终判读 集合的数量就是答案,
- 这题 要注意的是怎么判读:当前的某个农田x与,水平/竖直方向的农田可以连通?
- 我们讨论:x与相邻水平方向的农田的连通的的判断条件,我们设x左边的那块农田为y,如果x与y连通,要求:x在水平靠左方向左方向上有管道,而且还要求y在水平向右的方向上也有管道,这样就可以确定x与y判断连通,在实际的代码上就是用一个二维数mv[][]组预处理11种管道在四个方向上是否有指向的水管接头,通过x、y农田中的管道类型去访问mv从而获得x、y农田水管接头的方向
最后给自己提醒一下:给农田求编号的时候 乘的是列数
代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <unordered_map>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define m_p make_pair
#define INF 0x3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)
#define sc scanf
#define sd(a) scanf("%d", &a)
#define ss(a) scanf("%s", a)
#define pr printf
using namespace std;
const int mxn = 55;
int n, m;
int mz[mxn][mxn];
int mv[15][4];
int a[mxn * mxn];
void get_mv()
{
mv[0][0] = 1, mv[0][1] = 0, mv[0][2] = 1, mv[0][3] = 0;
mv[1][0] = 1, mv[1][1] = 0, mv[1][2] = 0, mv[1][3] = 1;
mv[2][0] = 0, mv[2][1] = 1, mv[2][2] = 1, mv[2][3] = 0;
mv[3][0] = 0, mv[3][1] = 1, mv[3][2] = 0, mv[3][3] = 1;
mv[4][0] = 1, mv[4][1] = 1, mv[4][2] = 0, mv[4][3] = 0;
mv[5][0] = 0, mv[5][1] = 0, mv[5][2] = 1, mv[5][3] = 1;
mv[6][0] = 1, mv[6][1] = 0, mv[6][2] = 1, mv[6][3] = 1;
mv[7][0] = 1, mv[7][1] = 1, mv[7][2] = 1, mv[7][3] = 0;
mv[8][0] = 0, mv[8][1] = 1, mv[8][2] = 1, mv[8][3] = 1;
mv[9][0] = 1, mv[9][1] = 1, mv[9][2] = 0, mv[9][3] = 1;
mv[10][0] = 1, mv[10][1] = 1, mv[10][2] = 1, mv[10][3] = 1;
}
void init(int n, int m)
{
for_(i, 0, n * m)
a[i] = i;
}
int find(int x)
{
if(a[x] == x)
return x;
return a[x] = find(a[x]);
}
void Union(int x, int y)
{
int fx = find(x);
int fy = find(y);
if(fx != fy)
a[fx] = fy;
}
int main()
{
/* fre(); */
get_mv();
while(sc("%d %d ", &n, &m) && n >= 0 && m >= 0)
{
init(n, m);
char ch;
for_(i, 0, n - 1)
for_(j, 0, m - 1)
sc("%c ", &ch), mz[i][j] = ch - 'A';
for_(i, 0, n - 1)
for_(j, 0, m - 1)
{
int x = i * m + j, y, t; //注意这里 乘的是 m ---列数啊!!!!
int num = mz[i][j];
t = mz[i - 1][j];
if(i - 1 >= 0 && mv[num][0] && mv[t][1])
{
y = (i - 1) * m + j;//注意这里 乘的是 m ---列数啊!!!!
Union(x, y);
}
t = mz[i][j - 1];
if(j - 1 >= 0 && mv[num][2] && mv[t][3])
{
y = i * m + j - 1;//注意这里 乘的是 m ---列数啊!!!!
Union(x, y);
}
}
int ans = 0;
for_(i, 0, n - 1)
for_(j, 0, m - 1)
{
int num = i * m + j; //注意这里 乘的是 m ---列数啊!!!!
if(a[num] == num)
ans ++;
}
printf("%d\n", ans);
}
return 0;
}