CCF 201909-3 字符畫

CCF 201909-3 字符畫

題意:

  • 將n * m的RGB圖片壓縮成q * p的塊,每塊爲該原像素的平均值,咱們暫且稱之爲像素塊(代碼註釋爲字符塊)ios

  • 輸入n行m列的RGB圖片:spa

    • 第一行:圖片的寬m高n
    • 第二行:要壓縮的單位寬p高q,即對原圖片的每q*p個像素取平均值獲得像素塊,保證輸入獲得整數個像素塊。
    • 接下來n*m行,自上到下,自左往右輸入圖片的HTML格式的像素:
      • #a 表示RGB(0xaa,0xaa,0xaa)
      • #abc 表示RGB(0xaa,0xbb,0xcc)
      • #abcdef 表示RGB(0xab,0xcd,0xef)
  • 輸出壓縮後的圖片的背景色.net

    • 像素塊行處理:
      • 若背景色與該行的像素塊的前一塊(第一塊與默認值比較)顏色相同,則不處理;不然若與默認值相同則輸出 ESC[0m 的格式化表示,不相同則輸出 ESC[48;2;R;G;Bm 的格式化表示(此處RGB指代像素塊的RGB)。
      • 每個像素塊後必須緊跟一個格式化的空格: \x20
    • 像素塊行尾處理:
      • 若該行的最後一個像素塊顏色不是默認值則輸出 ESC[0m 的格式化表示。
      • 始終在像素塊行尾追加一個格式化的回車: \x0A

考點:

  • 字符串進制轉換
  • 遞推循環
  • 數字按位分割

        上面引自Herecode

 

 

 

 

//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');//輸出n/q個回車 
    }
    return 0;
}
相關文章
相關標籤/搜索