题目:奶牛的艺术
题目描述
一个有关奶牛的鲜为人知的事实是她们都是红绿色盲,也就是说,在她们看来,红色和绿色是一样的(译者注:奶牛把这种颜色称作“红绿色”)。这使得我们设计的艺术作品难以同时符合人类和奶牛的审美口味。
考虑一个由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;
}