题目大意
考点
各种进制转换与ascii编码 + 阅读理解
思路
这题个人认为是CSP历年第三题里最坑的一道,因为出题人比较拐弯抹角,没有直接告诉你一些条件。比如:这道题给出了前景色和背景色的概念,却没告诉你应该用哪种色,而是隔了好多行,藏了一句话:“空格用来绘制色块(呈现出的即为背景色)”。也就是说,本题只用到背景色!当时我注意到了,可是我不敢直接忽略前景色,犹豫了好久。
由于本题流程较复杂,所以读完题后脑海里要形成一个流程:矩阵分块求平均–>按顺序生成指令–>指令ascii码转十六进制,每个流程都要有一个大致思路。然后模拟即可。
另外值得注意的是,本题有三种颜色,最好是用二维结构体数组存像素,我用三维矩阵存像素会超时,可能跟空间局部性有关?
易错点
- 分块前和分块后,矩阵的下标不同,务必注意。由于都是题目给出的都是小样例,你很难发现通过题目的样例发现自己的错误!
- 各种转码操作不能错
- 逻辑理清楚
收获
- 能用结构体的话,别用更高维的数组
满分代码
//按要求模拟,不急不躁,一步一个脚印!
//2000*1000*3
#include <bits/stdc++.h>
using namespace std;
const int N=3e3+10,M=3010,mod=998244353;
#define pb push_back
#define se second
#define fi first
typedef long long LL;
typedef pair<LL,LL> PII;
typedef struct Rgb{
int r,g,b;
}rgb;
int m,n,p,q;
rgb mat[N][M],gg[N][M];
string col;
string smod="\\x1B\\x5B\\x34\\x38\\x3B\\x32";//事先准备好的模板
string esc="\\x1B\\x5B\\x30\\x6D";
string slas="\\x6D";
string kg="\\x20";
string fh="\\x3B";
string newrow="\\x0A";
string ans;
char tochar(int x){
if(x<10)return '0'+x;
else return 'A'+x-10;
}
string hexcode(int x){ //获得该数的hex编码
string s;
int hi=x/16,lo=x%16;
s.insert(0,1,tochar(lo));
s.insert(0,1,tochar(hi));
s="\\x"+s;
return s;
}
string tohex(int x){
if(x==0){ //!!!
return hexcode('0');
}
vector<string>vs;
string tts;
while(x){
int res=x%10;
tts.insert(0,hexcode(res+'0'));///!!!!
x/=10;
}
return tts;
}
int tocharint(char x){
if(isdigit(x))return x-'0';
else return 10+x-'a'; ///!!!!!!!!!!!!!!!!!!!!
}
int toint(string s){
int low=tocharint(s[1]),high=tocharint(s[0]);
return low+high*16;
}
int main(){
cin>>m>>n>>p>>q;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
cin>>col;
int len=(int)col.length()-1;
if(len==6){
mat[i][j].r=toint(col.substr(1,2));
mat[i][j].g=toint(col.substr(3,2));
mat[i][j].b=toint(col.substr(5,2));
}
else if(len==3){
string sr,sg,sb;
sr.insert(0,2,col[1]);
sg.insert(0,2,col[2]);
sb.insert(0,2,col[3]);
mat[i][j].r=toint(sr);
mat[i][j].g=toint(sg);
mat[i][j].b=toint(sb);
}
else{
string sr;
sr.insert(0,2,col[1]);
int x=toint(sr);
mat[i][j].r=mat[i][j].g=mat[i][j].b=x;
}
}
for(int i=0;i<n;i+=q){
for(int j=0;j<m;j+=p){//枚举左上角的点
int sr=0,sg=0,sb=0;
for(int x=i;x<i+q;x++){
for(int y=j;y<j+p;y++){
sr+=mat[x][y].r;
sg+=mat[x][y].g;
sb+=mat[x][y].b;
}
}
//cout<<sr<<" "<<sb<<endl;
gg[i/q][j/p].r=sr/(p*q);
gg[i/q][j/p].g=sg/(p*q);
gg[i/q][j/p].b=sb/(p*q);//!!!
//cout<<g[i/q][j/p].r<<" "<<g[i/q][j/p].b<<" "<<g[i/q][j/p].b<<endl;
}
}
int tr,tg,tb;
int lr=0,lg=0,lb=0;//每行的背景色都是0
for(int i=0;i<n/q;i++){
for(int j=0;j<m/p;j++){
rgb tmp=gg[i][j];
tr=tmp.r;tg=tmp.g;tb=tmp.b;
if(tr!=lr || tg!=lg || tb!=lb){
if(tr==0 && tg==0 && tb==0){
ans+=esc;
}
else{
ans+=smod;
ans+=fh;
ans+=tohex(tr);
ans+=fh;
ans+=tohex(tg);
ans+=fh;
ans+=tohex(tb);
ans+=slas;
}
}
lr=tr;
lg=tg;
lb=tb;
ans+=kg;
}
if(tr!=0 || tg!=0 || tb!=0)ans+=esc; //最后还原状态!!!
lr=0;lg=0;lb=0;
ans+=newrow;
}
cout<<ans;
return 0;
}