CCF 201909-3 字符画

CCF 201909-3 字符画

题意:

  • 将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

考点:

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

        上面引自Here

 

 

//100分 453ms
#include<iostream>
#include<iomanip>
#define OPT __attribute__((optimize("O3")))
using namespace std;
const int N=2e3;
short c[N][N][3];//c[n][m][Pixel:RGB] 表示原图片在第n行m列的像素颜色
int m,n,p,q,PQ,R,G,B,r,g,b,num[10];string s;
OPT inline short getCell(const char &a,const char &b){//将16进制像素数转换为10进制的char 
    return (isalpha(a)?(10+a-'a'):(a-'0'))*16+(isalpha(b)?(10+b-'a'):(b-'0'));
}
OPT inline void outChar(const char &ch){//输出题意格式化的字符 
    cout<<"\x"<<hex<<uppercase<<setw(2)<<int(ch);
}
OPT inline void outStr(const string &str){//输出题意格式化的字符串 
    for(const char &ch:str) outChar(ch);
}
inline void outCell(int x){
    int cnt(0);
    if(!x) num[++cnt]=0;
    for(;x;x/=10) num[++cnt]=x%10;
    for(int i=cnt;i;i--) outChar(char(num[i]+'0'));
}
OPT int main(){
    ios::sync_with_stdio(false);
    cin>>m>>n>>p>>q,PQ=p*q,cout.fill('0');
    for(int i=1;i<=n;i++){
        for(int j=1,len;j<=m;j++){
            cin>>s;len=s.length();
            switch(len){//统一格式标准化为 #abcdef 
                case 2:s=s+string(5,s[1]);break;
                case 4: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]=getCell(tolower(s[k*2+1]),tolower(s[k*2+2]));
        }
    }
    for(int i=1;i<=n;i+=q){//共n/q个字符块行 
        for(int j=1;j<=m;j+=p){//每字符块行共m/p段 
            R=G=B=0;//以下处理属于i行j段的字符块
            for(int k=i,ke=k+q;k<ke;k++)
                for(int l=j,le=j+p;l<le;l++)
                    R+=c[k][l][0],G+=c[k][l][1],B+=c[k][l][2];
            R/=PQ,G/=PQ,B/=PQ;//求平均值 
            if(R!=r||G!=g||B!=b){//如果与该行上一段的颜色不同 
                if(!R&&!G&&!B)//如果与默认值相同 
                    outStr(string(1,char(27))+"[0m");
                else//其他颜色处理 
                    outStr(string(1,char(27))+"[48;2;"),outCell(R),outChar(';'),outCell(G),outChar(';'),outCell(B),outChar('m');
                r=R,g=G,b=B;//记录上次的颜色 
            }
            outChar(' ');//输出 (n*m)/(p*q) 个空格    
        }
        if(R||G||B) outStr(string(1,char(27))+"[0m");//行尾判断是否需要重置颜色
        r=g=b=0;//重置默认颜色 
        outChar('
');//输出n/q个回车 
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/11783987.html