CCF CSP 认证 201909-3 字符画 100分 2250ms

点击前往试题目录:https://blog.csdn.net/best335/article/details/99550556

搜索页标题有问题 特重写一篇

在这里插入图片描述

解题思路

吐槽:

  • 这道题题意描述不明确,差评。
  • 对图片压缩显示,但描述似乎有问题,那么问题来了,什么时候画前景色,什么时候画背景色?题目描述字符改前景色,样例输出字符又改了背景色。
    在输出那部分出题人说:空格用于绘制色块(呈现出的即为背景色),转义序列用于改变颜色。 拐着好几个弯说话,我只能说呵呵,再加上字符用前景色绘制,这一混淆,我呵呵呵呵。
    我们在windows环境下考试,扯什么Linux操作系统?
    测试样例覆盖有问题,总体来说难度偏高,理解题意后难度很低这道题,需要你细心,过滤废话。

题意:

  • 将n * m的RGB图片压缩成q * p的块,每块为该原像素的平均值,我们暂且称之为像素块(代码注释为字符块)

  • 输入n行m列的RGB图片:

    • 第一行:图片的宽m高n
    • 第二行:要压缩的单位宽p高q,即对原图片的每q*p个像素取平均值得到像素块,保证输入得到整数个像素块。
    • 接下来n*m行,自上到下,自左往右输入图片的HTML格式的像素:
      • #a 表示RGB(0xaa,0xaa,0xaa)
      • #abc 表示RGB(0xaa,0xbb,0xcc)
      • #abcdef 表示RGB(0xab,0xcd,0xef)
  • 输出压缩后的图片的背景色

    • 像素块行处理:
      • 若背景色与该行的像素块的前一块(第一块与默认值比较)颜色相同,则不处理;否则若与默认值相同则输出 ESC[0m 的格式化表示,不相同则输出 ESC[48;2;R;G;Bm 的格式化表示(此处RGB指代像素块的RGB)。
      • 每一个像素块后必须紧跟一个格式化的空格: \x20
    • 像素块行尾处理:
      • 若该行的最后一个像素块颜色不是默认值则输出 ESC[0m 的格式化表示。
      • 始终在像素块行尾追加一个格式化的回车: \x0A

考点:

  • 字符串进制转换
  • 递推循环
  • 数字按位分割

AC代码

#include<iostream>
#include<cstring>
#include<iomanip>
#include<vector>
using namespace std;
unsigned char C[1080][1920][3];//C[n][m][Pixel:RGB] 表示原图片在第n行m列的像素颜色 
inline unsigned char getPixel(const char&a,const char&b){//将16进制像素数转换为10进制的char 
	return char((isalpha(a)?(10+a-'a'):(a-'0'))*16+(isalpha(b)?(10+b-'a'):(b-'0')));
}
inline void outChar(const unsigned char&ch){//输出题意格式化的字符 
	cout<<"\\x"<<hex<<uppercase<<setw(2)<<int(ch);
}
inline void outStr(const string& str){//输出题意格式化的字符串 
	for(const char&c:str)outChar(c);
}
inline void outPixel(int i){//输出题意格式化的像素 
	vector<int> v;
	if(i==0)v.push_back(0);
	while(i>0) v.push_back(i%10),i/=10;//首先将数按位数分割 例:255 分割为 2、5、5三个数 
	for(i=v.size()-1;i>-1;--i) outChar(char('0'+v[i]));//输出每一位 
}
#include<fstream> 
int main(){
	int m,n,p,q,_B;// W H 
	ifstream cin("C:\\Users\\Isidore\\Desktop\\out.txt");
	cin>>m>>n>>p>>q,_B=p*q,cout.fill('0');
	string s;
	for(int i=0;i<n;++i){
		for(int j=0;j<m;++j){
			cin>>s;
			switch(s.size()){//将s统一格式化为 #abcdef 
				case 2://#a -> #aaaaaa 
					s=s+string(5,s[1]);
					break;
				case 4://#abc -> #aabbcc
					s="#"+string(2,s[1])+string(2,s[2])+string(2,s[3]);
					break;
			}
			for(int k=0;k<3;++k) C[i][j][k]=getPixel(tolower(s[k+k+1]),tolower(s[k+k+2]));
		}
	}
	int R=0,G=0,B=0,r=0,g=0,b=0;
	for(int i=0;i<n;i+=q){//共n/q个字符块行 
		for(int j=0;j<m;j+=p){//每字符块行共m/p段 
			R=0,G=0,B=0;//以下处理属于i行j段的字符块
			for(int k=i,nk=k+q;k<nk;++k)
				for(int l=j,nl=j+p;l<nl;++l)
					R+=C[k][l][0],G+=C[k][l][1],B+=C[k][l][2];
			R/=_B,G/=_B,B/=_B;//求平均值 
			if(!(R==r&&G==g&&B==b)){//如果与该行上一段的颜色不同 
				if(R==0&&G==0&&B==0)//如果与默认值相同 
					outStr(string(1,char(27))+"[0m");
				else//其他颜色处理 
					outStr(string(1,char(27))+"[48;2;"),outPixel(R),outChar(';'),outPixel(G),outChar(';'),outPixel(B),outChar('m');
				r=R,g=G,b=B;//记录上次的颜色 
			}
			outChar(' ');//输出 (n*m)/(p*q) 个空格 
		}
		if(R!=0||G!=0||B!=0) outStr(string(1,char(27))+"[0m");//行尾判断是否需要重置颜色 
		r=g=b=0;//重置默认颜色 
		outChar('\n');//输出n/q个回车 
	}
	return 0;
}

其他有帮助的代码

1 1
1 1
#010203

2 2
1 2
#111111
#0
#000000
#111

#include<iostream>
#include<cstring>
#include<iomanip>
using namespace std; 
inline char getHex(const char&a,const char&b){//将两个16进制表示的字符转换为10进制字符 
	return char((isalpha(a)?(10+a-'a'):(a-'0'))*16+(isalpha(b)?(10+b-'a'):(b-'0')));
}

inline void outRes(const string& str){//输出格式化的16进制字符串 
	for(int i=0,ni=str.size();i<ni;i+=3){
		int j=getHex(tolower(str[i+1]),tolower(str[i+2]));//调试
		cout<<getHex(tolower(str[i+1]),tolower(str[i+2]));
	}		
}

int main(){
	outRes("x1Bx5bx34x38x3Bx32x3bx31x3bx32x3bx33x6dx20x1bx5bx30x6dx0a");//样例1字符反输出
	outRes("x1bx5bx34x38x3bx32x3bx38x3bx38x3bx38x6dx20x20x1bx5bx30x6dx0a");//样例2字符反输出
	return 0;
}

发布了107 篇原创文章 · 获赞 21 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/best335/article/details/102154818
今日推荐