CCF-CSP題解 201909-3 字符畫【字符串處理+進制轉換】

題目鏈接

一杯茶,一根菸,一道模擬做一天。

字符畫

在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述

思路

輸出注意:
(1)初始時終端的背景色都爲默認值(背景黑色);
(2) 如果下一個字符的顏色剛好與默認值完全相同,應當直接使用重置轉義序列ESC[0m(即\x1B\x5B\x30\x6D),而非手動更改顏色;
(3)如果某個字符的背景色與其前一個字符相同則直接在前一個字符後輸入“空格”(\x20);
(4) 在每行(遇到/x0A幾位換行)結尾處,如果終端顏色不是默認值,應該重置終端的顏色狀態。
其他注意:
(1)計算每一小塊像素的平均值,並將計算出的像素值的ASCII編碼轉義爲16進制編碼形式,如像素爲255,55,5需要轉義爲/x32/x35/x35,/x35/x35,/x35。
(2)定義pg,pg,pb保存上一次像素值,每進行第一行或者新一行的運算時需要將pg,pg,pb初始化爲默認值0。然後將計算的像素平均值與pg,pg,pb或者默認值0,0,0比較來輸出相應的格式。

滿分代碼:

#include<iostream>
#include<string>
#include<iomanip>
#include<bitset>
#include<cmath>
#include<sstream>
using namespace std;

struct rgb{
    int r,g,b;
    rgb(int _r=0,int _g=0,int _b=0):r(_r),g(_g),b(_b){}
}block[1100][2000],resblock[1100][2000];

int to_int(string str){//故意寫複雜了,其實不需要
    int tmp;
    int num=0;
    int len=str.size();
    int carry;
    for(int i=0;i<len;i++){
        carry=len-1-i;
        if(str[i]>='a'&&str[i]<='z')
            tmp=str[i]-'a'+10;
        else if(str[i]>='A'&&str[i]<='Z')
            tmp=str[i]-'A'+10;
        else
            tmp=str[i]-'0';
        num+=pow(16,carry)*tmp;
    }
    return num;
}

void print(string str){//輸出
    for(int i=0;i<str.size();i++)                                   //轉爲ascii碼
        cout<<"\\x"<<hex<<uppercase<<setw(2)<<int(str[i]);
}

int main(){
    int m,n,p,q;
    cin>>m>>n>>p>>q;
    string color;
    //輸入
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin >> color;
            int r,g,b;
			if (color.size() == 2)
				color += string(5, color[1]);
			else if (color.size() == 4)
				color = string(1, color[0]) + string(2, color[1]) + string(2, color[2]) + string(2, color[3]);
            r=to_int(color.substr(1,2));
            g=to_int(color.substr(3,2));
            b=to_int(color.substr(5,2));
            block[i][j]=rgb(r,g,b);
            //cout<<r<<" "<<g<<" "<<b<<endl;
        }
    }
    //處理小塊,即求平均值
    for(int i=0;i<n/q;i++){
        for(int j=0;j<m/p;j++){
            int r=0,g=0,b=0;
            for(int ki=q*i;ki<q*(i+1);ki++){
                for(int kj=p*j;kj<p*(j+1);kj++){
                    r+=block[ki][kj].r;
                    g+=block[ki][kj].g;
                    b+=block[ki][kj].b;
                }
            }
            //cout<<r/(p*q)<<" "<<g/(p*q)<<" "<<b/(p*q)<<endl;
            resblock[i][j]=rgb(r/(p*q),g/(p*q),b/(p*q));
        }
    }
    //輸出每一個小塊
    int dr=0,dg=0,db=0;
    int pr=0,pg=0,pb=0;
    for(int i=0;i<n/q;i++){
        for(int j=0;j<m/p;j++){
            int r=resblock[i][j].r,g=resblock[i][j].g,b=resblock[i][j].b;
            if(r==pr&&g==pg&&b==pb){}//如果和前一個小塊一樣
            else if(r==dr&&g==dg&&b==db){//如果和默認一樣
                pr=dr,pg=dg,pb=db;//更新
                cout << "\\x1B\\x5B" << "\\x30\\x6D";
            }
            else{//如果都不一樣
                pr=r,pg=g,pb=b;//更新
                string rr,gg,bb;
                stringstream ss;//int->string,懶得寫個函數了,可能慢點
                ss<<r,ss>>rr,ss.clear();
                ss<<g,ss>>gg,ss.clear();
                ss<<b,ss>>bb,ss.clear();
                print("\x1b[48;2;"+rr+";"+gg+";"+bb+"m");//輸出
            }
            cout<<"\\x20";//每個小塊結束,都輸出一個空格
        }
        if(pr!=dr||pg!=dg||pb!=db){//換行判斷結尾是否爲默認值
            cout << "\\x1B\\x5B" << "\\x30\\x6D";
            pr=dr,pg=dg,pb=db;//更新爲默認值
        }
        cout<<"\\x0A";//輸出一個換行符
    }
	return 0;
}

測試樣例:

輸入1
1 1
1 1
#010203
 
輸出1
\x1B\x5B\x34\x38\x3B\x32\x3B\x31\x3B\x32\x3B\x33\x6D\x20\x1B\x5B\x30\x6D\x0A
 
輸入2
2 2
1 2
#111111
#0
#000000
#111
 
輸出2
\x1B\x5B\x34\x38\x3B\x32\x3B\x38\x3B\x38\x3B\x38\x6D\x20\x20\x1B\x5B\x30\x6D\x0A
 
 
輸入3
1 1
1 1
#0
 
輸出3
\x20\x0A
 
 
輸入4
2 2
2 1
#111111
#0
#000000
#111
 
輸出4
\x1B\x5B\x34\x38\x3B\x32\x3B\x38\x3B\x38\x3B\x38\x6D\x20\x1B\x5B\x30\x6D\x0A\x1B\x5B\x34\x38\x3B\x32\x3B\x38\x3B\x38\x3B\x38\x6D\x20\x1B\x5B\x30\x6D\x0A
 
輸入5
2 2
2 1
#111111
#0
#000000
#000
輸出5
\x1B\x5B\x34\x38\x3B\x32\x3B\x38\x3B\x38\x3B\x38\x6D\x20\x1B\x5B\x30\x6D\x0A\x20\x0A
 
 
輸入6
3 2
1 2
#0
#0
#010101
#010102
#0
#0
輸出6
\x1B\x5B\x34\x38\x3B\x32\x3B\x30\x3B\x30\x3B\x31\x6D\x20\x1B\x5B\x30\x6D\x20\x20\x0A
 
 
輸入7
1 2
1 2
#123456
#abcdef
輸出7
\x1B\x5B\x34\x38\x3B\x32\x3B\x39\x34\x3B\x31\x32\x38\x3B\x31\x36\x32\x6D\x20\x1B\x5B\x30\x6D\x0A
 
輸入8
2 1
2 1
#654321
#fedcba
輸出8
\x1B\x5B\x34\x38\x3B\x32\x3B\x31\x37\x37\x3B\x31\x34\x33\x3B\x31\x30\x39\x6D\x20\x1B\x5B\x30\x6D\x0A
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章