[USACO2014Bronze]奶牛艺术

如你所见,今天也是一道奶牛的题(奶牛万岁!)

我们先来看题:

描述

一个关于奶牛的鲜为人知的事实是它们其实是红绿色盲,也就是说红色和绿色在它们看来完全一样。

这使得设计出对奶牛和人类都有巨大吸引力的艺术作品变得非常困难。

考虑一个正方形绘画,它用一个字符矩阵来描述,每个字符要么是 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;
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值