CCF考试 201909-3 字符画C++100分简单易懂思路讲解。使用的是C++11.
这个题的题干很长,其实有用的东西没几句话,我们不需要对含有字符的进行处理。只需要处理空格的那种情况就好了,也就是只需要对背景涂色就可以了。首先,我们声明了一个二维数组,用来存取输入的颜色。
然后,我们把他的缩写输入还原回来。都还原成长度为6的字符串(handleCon函数)。
然后我们就着手准备输出。我们要先考虑几种题干给出的特殊情况。
- 如果下一个字符和之前的一样,直接输出空格
- 如果下一个字符和默认的一样,输出重置序列,就是
ESC[0m这个东西。 - 输出一行之后,如果当前的颜色和默认的不同,要执行重置序列
- 输出一行之后,要输出换行序列。
大概就是这么几个需要注意的点,在代码中体现出来就好,下面对我的代码进行简单的梳理。方便读者理解这个题的思路。
- 利用一个for循环,读取输入。
- 声明rSava,bSava,gSava用来存取上一个颜色,方便处理。
- 对这个颜色块进行循环,使程序可以扫描到每个颜色块
- 在3的基础上,去找颜色小块,对他进行平均处理。在做平均的时候,要将string转化为int(调用了strToInt函数)
- 求完平均之后,进行特殊情况判定,是否为上述特殊情况1或2,分别对应不同输出,如果不是特殊情况,就要输出更改颜色的代码(changColor函数),在这个函数中,我们对把颜色转化为输出的形式,再按照题干要求输出。
- 进行最后的判断,上述情况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;
}