Do not pursue the most concise code, pursue the most readable code, and strive to make the reader understand and write the code again
Examination questions
According to the meaning of the topic, the color of the area entered in each line does not distinguish the foreground color and background color. The topic changes the background color, so only the background color is changed by default.
1. The foreground color and background color of the terminal are default values at the beginning (foreground white, background black)
If the foreground or background color calculated by the first area is the default value, you do not need to output to the terminal, but you need to output spaces.
2. If the next character and color exactly match the default, you should use the reset escape sequence instead of manually changing the color.
3. If the foreground / background color of a character is the same as its previous character, or the change of color does not affect the final display effect, the control sequence of changing this property should not appear.
Don't forget to output space.
4. After entering each line of characters, if the terminal color is not the default value, you should reset the terminal color status.
Line feed is also required at the end of each line \ n
5. Special cases need to be handled. aabbcc can be written as "abc" and "aaaaaa" can be written as "a"
In three cases, let's deal with okk alone
2, Algorithm strategy
1. Color storage, color conversion, use dot [m][n] to mark the color of any coordinate.
struct dot{ int R; int G; int B; dot(int a,int b,int c){ R = a; G = b; B = c; } }
Convert string to dot and take out a function separately.
3. For area calculation, the number of areas is (mn)/(pq), and the number of lines is n/q. use vector link, and pay attention to the area branch.
4. The initial background color and foreground color are set as the precursor at the beginning of each line, and the precursor is marked to omit the change of color.
5. Don't leave out the situation given by the subject when simulating. Control it strictly in the macro level, and then realize it locally.
void outputRGB() { int size = list.size(); //Number of blocks in a region int gap = m/p; // gap areas per line int i; dot pre; //Previous area dot curr; //Current region for(i=0;i<size;i++) { curr = list[i]; if(i%gap == 0) // 1. The first in each line sets the front color as the default background color pre = defaultDot; if(isEqual(curr,pre)) // 2. The current color is the same as the precursor color. Output a space without changing outputSpace(); else if(isEqual(curr,defaultDot)){ // 3. The current color is the default background color outputDefaultRGB(); // Output reset terminal, not current color outputSpace(); //Output a space } else{ // Common output outputSingleRGB(curr); } if( (i+1)%gap ==0 && !isEqual(curr,defaultDot)){ // The last one in each line is not the default color outputDefaultRGB(); } if( (i+1)%gap == 0 ) // Last in each line printf(R"(\x0A)"); //Output'\n' pre = curr; // Update forerunner } }
After making sure that the appeal does not miss the situation given by the title, implement the subfunction again.
The final AC code is as follows.
#include <iostream> #include <cstdio> #include <string> #include <vector> using namespace std; int m,n; int p,q; struct dot{ int R; int G; int B; dot(int a,int b,int c){ R = a; G = b; B = c; } dot(){ R=G=B=0; } }; dot arr[1100][2000]; dot defaultDot(0,0,0); // Default background color vector<dot> list; int toAscii(char ch) { if(ch>='a') return ch-'a'+10; else return ch-'0'; } dot strToDot(string str) { str.erase(str.begin()); //Remove lead# dot res; int len = str.length(); if(len == 6){ res.R = toAscii(str[0])*16 + toAscii(str[1]); res.G = toAscii(str[2])*16 + toAscii(str[3]); res.B = toAscii(str[4])*16 + toAscii(str[5]); } else if(len == 1){ str += str[0]; res.R = res.G = res.B = toAscii(str[0])*16 + toAscii(str[1]); } else{ //len = 3 res.R = toAscii(str[0])*16 + toAscii(str[0]); res.G = toAscii(str[1])*16 + toAscii(str[1]); res.B = toAscii(str[2])*16 + toAscii(str[2]); } return res; } dot countDot(int row,int endRow,int col,int endCol) { dot res; int i,j; for(i=row;i<endRow;i++) for(j=col;j<endCol;j++) { res.R += arr[i][j].R; res.G += arr[i][j].G; res.B += arr[i][j].B; } int area = (endRow-row)*(endCol-col); res.R /= area; res.G /= area; res.B /= area; return res; } bool isEqual(dot a,dot b) { return (a.R==b.R && a.G==b.G && a.B==b.B); } void outputDefaultRGB() { printf(R"(\x1B\x5B\x30\x6D)"); // ESC[0m } void outputNumber(int num) { string str; str = to_string(num); for(char i : str) { int a = int(i); //Convert to ascii code printf(R"(\x)"); printf("%X",a); } } void outputSingleRGB(dot curr) { printf(R"(\x1B\x5B\x34\x38\x3B\x32\x3B)"); // ESC[48;2; outputNumber(curr.R); printf(R"(\x3B)"); outputNumber(curr.G); printf(R"(\x3B)"); outputNumber(curr.B); printf(R"(\x6D\x20)"); // m+space } void outputSpace() { printf(R"(\x20)"); } void outputRGB() { int size = list.size(); int gap = m/p; // gap areas per line int i; dot pre; //Previous area dot curr; //Current region for(i=0;i<size;i++) { curr = list[i]; if(i%gap == 0) // 1, The first setting in each line is the default background color pre = defaultDot; if(isEqual(curr,pre)) // 2. The current color is the same as the precursor color. Output a space without changing outputSpace(); else if(isEqual(curr,defaultDot)){ // 3. The current color is the default background color outputDefaultRGB(); // Output reset terminal, not current color outputSpace(); //Output a space } else{ // Common output outputSingleRGB(curr); } if( (i+1)%gap ==0 && !isEqual(curr,defaultDot)){ // The last one in each line is not the default color outputDefaultRGB(); } if( (i+1)%gap == 0 ) // Last in each line printf(R"(\x0A)"); //Output'\n' pre = curr; // Update forerunner } } int main() { cin>>m>>n; cin>>p>>q; int i,j; string str; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { cin>>str; arr[i][j] = strToDot(str); } i = j = 1; while( i<=n ) { dot t = countDot(i,i+q,j,j+p); list.push_back(t); j += p; if( j > m ) { j = 1; i += q; } } outputRGB(); return 0; }