CCF考试 201909-3 字符画C++100分简单易懂思路讲解。

CCF考试 201909-3 字符画C++100分简单易懂思路讲解。使用的是C++11.

这个题的题干很长,其实有用的东西没几句话,我们不需要对含有字符的进行处理。只需要处理空格的那种情况就好了,也就是只需要对背景涂色就可以了。首先,我们声明了一个二维数组,用来存取输入的颜色。
然后,我们把他的缩写输入还原回来。都还原成长度为6的字符串(handleCon函数)。
然后我们就着手准备输出。我们要先考虑几种题干给出的特殊情况。

  • 如果下一个字符和之前的一样,直接输出空格
  • 如果下一个字符和默认的一样,输出重置序列,就是ESC[0m 这个东西。
  • 输出一行之后,如果当前的颜色和默认的不同,要执行重置序列
  • 输出一行之后,要输出换行序列。

大概就是这么几个需要注意的点,在代码中体现出来就好,下面对我的代码进行简单的梳理。方便读者理解这个题的思路。

  1. 利用一个for循环,读取输入。
  2. 声明rSava,bSava,gSava用来存取上一个颜色,方便处理。
  3. 对这个颜色块进行循环,使程序可以扫描到每个颜色块
  4. 在3的基础上,去找颜色小块,对他进行平均处理。在做平均的时候,要将string转化为int(调用了strToInt函数
  5. 求完平均之后,进行特殊情况判定,是否为上述特殊情况1或2,分别对应不同输出,如果不是特殊情况,就要输出更改颜色的代码(changColor函数),在这个函数中,我们对把颜色转化为输出的形式,再按照题干要求输出。
  6. 进行最后的判断,上述情况3和4

这个题并不难,有一些字符串处理的东西,熟悉之后就好。
在这里插入图片描述
采用C++11是因为使用了to_stirng函数。

#include <iostream>
#include <string>

using namespace std;
string photo[1080][1920];
string chongZhi = "\\x1B\\x5B\\x30\\x6D";

string handleCon(string photoContent) {  //对几种不同的输入转化为统一的,都转化为长度为6的字符串
	string Content="";
	if (photoContent.length() == 7) {//#abcdef
		Content =Content+ photoContent[1] +
			photoContent[2] + photoContent[3] + photoContent[4] + photoContent[5] + photoContent[6];
	}
	else if (photoContent.length() == 4) {//#abc
		Content = Content + photoContent[1] +
			photoContent[1] + photoContent[2] + photoContent[2] + photoContent[3] + photoContent[3];
	}
	else if (photoContent.length() == 2) {//#a
		Content = Content + photoContent[1] +
			photoContent[1] + photoContent[1] + photoContent[1] + photoContent[1] + photoContent[1];
	}
	return Content;
}
int strToInt(char str1, char str2) { //将char转化为int
	int num = 0;
	if (str1 >= 'a') num += (str1 - 'a' + 10) * 16;
	else num += (str1 - '0') * 16;
	if (str2 >= 'a') num += (str2 - 'a' + 10);
	else num += (str2 - '0');
	return num;
}

string handleIntToCout(int color) {//将具体的数转化为题干要求的十六进制输出
	string a;
	if (color >= 100) {
		int baiWei = color / 100;
		baiWei += 30;
		int shiWei = (color%100) / 10;
		shiWei += 30;
		int geWei = color % 10;
		geWei += 30;
		a = "\\x" + to_string(baiWei) + "\\x" + to_string(shiWei)+"\\x" + to_string(geWei);
	}
	else if (color >= 10) {
		int shiWei = color/10;
		shiWei += 30;
		int geWei = color % 10;
		geWei += 30;
		a = "\\x" + to_string(shiWei) + "\\x" + to_string(geWei);
	}
	else {
		int geWei = color;
		geWei += 30;
		a = "\\x" + to_string(geWei);
	}
	return a;
}

string changeColor(int r,int g,int b) {//将RGB颜色转化为题干要求输出的样子
	string R = handleIntToCout(r);
	string G = handleIntToCout(g);
	string B = handleIntToCout(b);
	string a = "\\x1B\\x5B\\x34\\x38\\x3B\\x32\\x3B"+R+"\\x3B"+G+"\\x3B"+B+"\\x6D";
	return a;
}
int main() {
	ios::sync_with_stdio(false);  //减少cin时间 第三题必用
	int m, n,p,q;//m是宽,n是高,p是小块宽,q是小块高
	cin >> m >> n >> p >> q;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			string photoContent;
			cin >> photoContent;
			photo[i][j] = handleCon(photoContent).c_str();//获取之后的字符,都为六字符
		}
	}


	int rSava = 0;
	int gSava = 0;
	int bSava = 0;
	for (int i = 0; i < n; i=i+q)
	{

		for (int j = 0; j < m; j=j+p)//前两个循环是找寻所有像素块,下两个循环是取块内平均值
		{
			int red=0, green=0 ,blue=0;
			for (int height = i; height < q+i; height++)
			{
				for (int width  = j; width < p+j; width++)
				{
					red += strToInt(photo[height][width][0] , photo[height][width][1]);
					green += strToInt(photo[height][width][2] ,photo[height][width][3]);
					blue += strToInt(photo[height][width][4] , photo[height][width][5]);
				}
			}
			red = red / (p*q); green = green / (p*q); blue = blue / (p*q);//取平均
			if (red == rSava && green == gSava && blue == bSava) { //如果和之前的相等
				cout << "\\x20";
			}
			else if (red == 0 && green == 0 && blue == 0) {
				rSava = red; gSava = green; bSava = blue;
				cout << chongZhi<<"\\x20";
			}
			else{//如果和之前的不相等
				rSava = red; gSava = green; bSava = blue;

				string result = changeColor(red, green, blue);
				result = result + "\\x20";
				cout << result;
			}
			
		}
		if (rSava != 0 || gSava != 0 || bSava != 0) { 
			rSava = 0; gSava = 0; bSava = 0;
			cout << chongZhi;
		}
		cout << "\\x0A";

	}

	return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值