如你所见,今天也是一道奶牛的题(奶牛万岁!)
我们先来看题:
描述
一个关于奶牛的鲜为人知的事实是它们其实是红绿色盲,也就是说红色和绿色在它们看来完全一样。
这使得设计出对奶牛和人类都有巨大吸引力的艺术作品变得非常困难。
考虑一个正方形绘画,它用一个字符矩阵来描述,每个字符要么是 R(红色),要么是 G(绿色),要么是 B(蓝色)。
如果一幅画有许多可以彼此区分的彩色“区域”,那么它就很有趣。
如果两个字符直接相邻(东、西、南或北),并且在颜色上无法区分,则它们属于同一区域。
例如,下列图画:
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
在人看来有 4 个区域(2 个红色区域,1 个蓝色区域,1 个绿色区域),而在牛看来只有 3 个区域(2 个红绿区域,1 个蓝色区域)。
给定一幅画作,请计算该画作在人和牛眼中的区域数量。
输入描述
第一行包含整数 N。
接下来 N 行,每行包含一个长度为 N 的字符串,用来描述画作。
输出描述
两个整数,分别表示人和牛眼中的区域数量。
用例输入 1:
5
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
用例输出 1:
4 3
数据范围与提示:
1≤N≤100
题目就是这样,如果你仔细看题(不仔细也无所谓),就能发现这是一道裸dfs。
相信聪明的你很快就能把dfs写出。
void dfs(int x, int y)
{
b[x][y] = true;
for (int i = 0; i < 4; i++)
{
int x1 = x + dx[i];
int y1 = y + dy[i];
if (x1 < 0 || x1 >= n || y1 < 0 || y1 >= n)
continue;
if (c[x][y] == c[x1][y1] && b[x1][y1] == false)
dfs(x1, y1);
}
}
然后就可以定义变量了。
int n, ans, ans2, dx[5] = {-1, 0, 1, 0}, dy[5] = {0, 1, 0, -1};
char c[105][105];
bool b[105][105];
接下来输入。
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> c[i][j];
我们先计算人类能看到的色块数。
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (b[i][j] == false)
{
ans++;
dfs(i, j);
}
然后计算奶牛能看到的色块数。
memset(b, false, sizeof(b));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (c[i][j] == 'G')
c[i][j] = 'R';
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (b[i][j] == false)
{
ans2++;
dfs(i, j);
}
最后输出。
printf("%d %d\n", ans, ans2);
把代码段组合起来,得到代码。
#include <bits/stdc++.h> // 万能头文件
using namespace std;
int n, ans, ans2, dx[5] = {-1, 0, 1, 0}, dy[5] = {0, 1, 0, -1};
char c[105][105];
bool b[105][105];
void dfs(int x, int y)
{
b[x][y] = true; // 设置点(x, y)遍历过了
for (int i = 0; i < 4; i++)
{
int x1 = x + dx[i]; // x1临时存储x
int y1 = y + dy[i]; // y1临时存储y
if (x1 < 0 || x1 >= n || y1 < 0 || y1 >= n)
continue;
if (c[x][y] == c[x1][y1] && b[x1][y1] == false)
dfs(x1, y1); // 如果一样,则继续遍历
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> c[i][j];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (b[i][j] == false) // 证明点(i, j)没有被遍历过
{
ans++; // 人类能看见的色块+1
dfs(i, j);
}
memset(b, false, sizeof(b)); // 为了计算方便,b数组重新变为每个点都没遍历过
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (c[i][j] == 'G') // 奶牛无法区分红色和绿色,这里统一归类于绿色
c[i][j] = 'R';
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (b[i][j] == false) // 证明点(i, j)没有被遍历过
{
ans2++; // 奶牛能看见的色块+1
dfs(i, j);
}
printf("%d %d\n", ans, ans2);
return 0;
}