点击前往试题目录:https://blog.youkuaiyun.com/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;
}