奶牛的艺术C++题解

题目:奶牛的艺术

题目描述

一个有关奶牛的鲜为人知的事实是她们都是红绿色盲,也就是说,在她们看来,红色和绿色是一样的(译者注:奶牛把这种颜色称作“红绿色”)。这使得我们设计的艺术作品难以同时符合人类和奶牛的审美口味。
考虑一个由N x N格字符表示的方形绘画作品,其中每个字符为R(红),G(绿)或者B(蓝)。一幅绘画如果有许多互不相同的着色“区域”,则我们认为它是有趣的。如果两个字符是直接相邻的(一个在另一个的东、南、西、北方向)且其表示的颜色相同,则这两个字符属于同一个区域。例如,下面这幅绘画作品:
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
如果由人类来看有4个区域(2个红色,1个蓝色和1个绿色区域),而如果由奶牛来看则只有3个区域(2个红绿色,1个蓝色区域)。
现给你一副绘画作为输入,请计算该作品由人类和奶牛来看分别有多少个区域。

输入

第1行:整数N(N<=100)。
第2..1+N行:每行包含一个长度为N的字符串,表示绘画作品的一行。

输出

第1行:两个空格隔开的整数,分别给出由人类和奶牛欣赏绘画作品时会看见多少个区域。

样例输入 
5
RRRBB
GGBBB
BBBRR
BBRRR
RRRRR
样例输出
4 3

分析

这不就是妥妥的DFS吗?

深搜部分

肥肠非常简单,我就不解释了。

void dfs(int x,int y){
	f[x][y] = true;
	for(int i = 1;i <= 4;i++){
		int tx = x + fx[i];
		int ty = y + fy[i];
		if(tx < 1 or tx > n or ty < 1 or ty > n){
			continue;
		}
		if(a[x][y] == a[tx][ty] and f[tx][ty] == false){
			dfs(tx,ty);
		}
	}
}

人能看到的色块

遍历二维数组,如果遇到没有标记的,就深搜。

memset(f,false,sizeof(f));
for(int i = 1;i <= n;i++){
	for(int j = 1;j <= n;j++){
		if(f[i][j] == false){
			people++;
			dfs(i,j);
		}
	}
}

奶牛能看见的颜色

因为奶牛是红绿色盲,所以把红色都转换为绿色。当然,把绿色转换为红色也行。

for(int i = 1;i <= n;i++){
	for(int j = 1;j <= n;j++){
		if(a[i][j] == 'R'){
			a[i][j] = 'G';
		}
	}
}
	

奶牛看见的色块

和人一样。

memset(f,false,sizeof(f));
for(int i = 1;i <= n;i++){
	for(int j = 1;j <= n;j++){
		if(f[i][j] == false){
			cow++;
			dfs(i,j);
		}
	}
}

整体代码

#include<bits/stdc++.h>
using namespace std;

//变量定义 
int n;//n*n的画作 
char a[110][110];//画作 
bool f[110][110];//标记数组 
int people = 0,cow = 0;//人和奶牛能看到的色块数 
int fx[5] = {0,1,0,-1,0};//试探方向x坐标数组 
int fy[5] = {0,0,-1,0,1};//试探方向y坐标数组 

//深搜 
void dfs(int x,int y){
	f[x][y] = true;//标记为已经访问过 
	for(int i = 1;i <= 4;i++){//依次尝试四个方向 
		int tx = x + fx[i];//储存尝试后的x坐标 
		int ty = y + fy[i];//储存尝试后的y坐标 
		//如果超过画作的边界,那么不成立 
		if(tx < 1 or tx > n or ty < 1 or ty > n){
			continue;
		}
		//如果满足颜色相同且没被标记过,则递归 
		if(a[x][y] == a[tx][ty] and f[tx][ty] == false){
			dfs(tx,ty);
		}
	}
}

int main(){
	//输入 
	cin>>n;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			cin>>a[i][j];
		}
	}
	
	//人能看见的色块 
	memset(f,false,sizeof(f));//初始化标记数组
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			if(f[i][j] == false){
				people++;
				dfs(i,j);
			}
		}
	}
	
	//奶牛能看见的颜色 
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			//把红色转换为绿色, 因为奶牛是红绿色盲 
			if(a[i][j] == 'R'){
				a[i][j] = 'G';
			}
		}
	}
	
	//奶牛能看见的色块 
	memset(f,false,sizeof(f));//初始化标记数组
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			if(f[i][j] == false){
				cow++;
				dfs(i,j);
			}
		}
	}
	
	//输出 
	cout<<people<<" "<<cow;
	
	return 0;
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值