题目描述
算法设计+题目分析
吐槽一下
题目极其复杂,做的时候看了十几分钟题目愣是没看懂,去网上看了其他同学做的一些blog,还是没看懂。。。然后对着感谢链接里的同学的代码梳理了一下,才明白题目要干嘛,由于个人原因,只能在Visual C++ 6.0里操作,所以很多C++11的函数不能用,但也正是不能用,对于早期的人来说能理解得更透一些。
算法设计+题目分析
1、 题目里说的什么字符画根本就不用管,这就是一个最低级的图像压缩的思想,就是对一块内的RGB三个通道求平均值;
2、所有的输出前都要有/x;
3、空格、换行、ESC都需要用ASCII十六进制输出;
4、算出一块的RGB平均值后,若不等于上一块的RGB且不等于初始值(全零),则用ASCII输出这个背景色的命令;若不等于上一块的RGB但等于初始值(全零),输出reset重置的ASCII;
5、每块后输出一个空格,每一行输出一个换行符;
5、每一行输出换行符之前,要判断当前的RGB与start(全零)是否相同,不同要输出重置的ASCII。
几个核心点
1、输入的RGB三通道为16进制字符串,需先转为10进制整型;
2、输出时注意\x转义符和按照16进制输出
注意点+记录点
1. struct初始化的时候不可赋值
2. 在早期C++编译器(Visual C++6.0)中如何整数转换成字符串
#include <sstream>
#include <string>
using namespace std;
int main(){
stringsteam ss;
string t;
int a=0;
ss<<a;
t=ss.str();
return 0;
}
3. 单引号和双引号的区别
在C中单引号实际上是一个整数值(ASCII),'A’和"A"是两个不同的,'A’的长度是1,"A"的长度是2
4. 如何输出16进制的ASCII
printf("\\x%02X", s[i])
\x的第一个右斜杠为转义符,%02X为输出16进制数,且少于2位时,补0
代码(100分)
环境
Visual C++6.0
#include <vector>
#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct node{
int R, G, B;
};
const int MAXN=2000;
node image[MAXN][MAXN];//图片矩阵
int X16_to_10(string s){//将16进制的字符串转为10进制整型
int a,b;
if (s[0]>='A' && s[0]<='Z') a=((s[0]-'A')+10)*16;
if (s[0]>='a' && s[0]<='z') a=((s[0]-'a')+10)*16;
if (s[0]>='0' && s[0]<='9') a=(s[0]-'0')*16;
if (s[1]>='A' && s[1]<='Z') b=s[1]-'A'+10;
if (s[1]>='a' && s[1]<='z') b=s[1]-'a'+10;
if (s[1]>='0' && s[1]<='9') b=s[1]-'0';
//cout<<a+b<<endl;
return a+b;
}
void output(string s, node cur){
for (int i=0; i<s.size(); i++){//找到RGB三个字符的位置
string t;
stringstream ss;
if (s[i]=='R' || s[i]=='G' || s[i]=='B'){
if(s[i]=='R') ss<<cur.R;
if(s[i]=='G') ss<<cur.G;
if(s[i]=='B') ss<<cur.B;
t=ss.str();
for (int j=0; j<t.size(); j++) printf("\\x%02X", t[j]);//按输出16进制输出
}else printf("\\x%02X", s[i]);
}
}
void output2(string s){
for (int i=0; i<s.size(); i++){
printf("\\x%02X", s[i]);
}
}
int main(){
//freopen("C:\\input.txt", "r", stdin);
string back="\x1b[48;2;R;G;Bm";//背景色
string reset="\x1b[0m";//重置
int m, n, p, q;//图片宽高和块宽高
cin>>m>>n>>p>>q;
string rgb;
for (int i=0; i<n; i++){//遍历每一个像素
for(int j=0; j<m; j++){
cin>>rgb;
if (rgb.size()==2) rgb+=string(5, rgb[1]);//#a变为#aaaaaa
if (rgb.size()==4) rgb="#"+string(2,rgb[1])+string(2,rgb[2])+string(2,rgb[3]);//#abc变为#aabbcc
//cout<<rgb<<endl;
image[i][j].R=X16_to_10(rgb.substr(1, 2));
image[i][j].G=X16_to_10(rgb.substr(3, 2));
image[i][j].B=X16_to_10(rgb.substr(5, 2));
}
}
node last, start;
last.R=last.G=last.B=start.R=start.G=start.B=0;
for (int ii=0; ii<n/q; ii++){//遍历每一个块
for (int jj=0; jj<m/p; jj++){
node cur;
cur.R=cur.G=cur.B=0;
for (int r=0; r<q; r++){//计算块内RGB之和
for (int s=0; s<p; s++){
cur.R+=image[ii*q+r][jj*p+s].R;
cur.G+=image[ii*q+r][jj*p+s].G;
cur.B+=image[ii*q+r][jj*p+s].B;
}
}
cur.R /=p*q;//求平均
cur.G /=p*q;
cur.B /=p*q;
if(cur.R!=last.R || cur.G!=last.G || cur.B!=last.B){
if (cur.R==start.R && cur.G==start.G && cur.B==start.B) output2(reset);
else output(back, cur);
}
last.R=cur.R;//更新last的状态为cur
last.G=cur.G;
last.B=cur.B;
printf("\\x%02X", ' ');
}
if (last.R!=start.R || last.G!=start.G || last.B!=start.B) output2(reset);//每一行后如果不一样,就重置
last.R=start.R;
last.G=start.G;
last.B=start.B;
printf("\\x%02X", '\n');//输出换行符
}
return 0;
}