P5730 【深基5.例10】顯示屏
阿新 • • 發佈:2020-07-13
https://www.luogu.com.cn/problem/P5730
P5730 【深基5.例10】顯示屏 題解
題目的意思很明確,要我們通過輸入的數字來構建一個顯示屏,使得上面顯示這些數字。
許多題解裡建立了一個三維char
陣列來儲存每一個數字,然後進行輸出,其中打表浪費了大量的時間。我想,既然樣例輸出裡就有現成的\(0 \to 9\)每一個數字的形狀,為什麼不直接拿過來用呢?
首先我建立了一個數組base_1
來儲存樣例輸出,注意這裡行和列的大小一定要準確,因為字串是以\0
結尾的,獨佔一個空間:
char base_1[5][40]={ "XXX...X.XXX.XXX.X.X.XXX.XXX.XXX.XXX.XXX", "X.X...X...X...X.X.X.X...X.....X.X.X.X.X", "X.X...X.XXX.XXX.XXX.XXX.XXX...X.XXX.XXX", "X.X...X.X.....X...X...X.X.X...X.X.X...X", "XXX...X.XXX.XXX...X.XXX.XXX...X.XXX.XXX", // 0 2 4 6 8 };
這裡的註釋0 2 4 6 8
是什麼意思,之後會提到。
我們將答案儲存在一張畫布(即“顯示屏”)內。now
是什麼意思,一會兒也會說。
char pict[6][9999];//畫布,即題目中的"顯示屏"。
int now=0;//表示這個數字應該在畫布的第幾個位置寫入
這裡我的想法是,掃描輸入的數字串,然後依次轉化成真實數字。接下來的工作是從base_1
中“摳取”需要的數字。根據上面的註釋,我們會發現,數字\(i\)在base_1
中對應的範圍是(只寫出橫向座標,縱向座標就是\(0 \to 4\)):\([4i,4i+2]\)。依據這個性質,我們就可以“摳取”需要的數字。
那麼怎麼把摳出來的數字寫入到畫布裡呢?這裡now
now
儲存的是下一個數字要在橫向座標的什麼位置輸入畫布。一開始,now=0
,然後插入一個數字(比如說\(0\))之後,now
就應該移到4
的位置。再在這裡插入一個數字1
。每次插入一個數字,now
就要後移4
格。它的作用相當於電腦游標。至於補全一列'.'
的時候,我們直接從now-1
的位置插入就行。
處理相對位置有點麻煩,詳見註釋。注意陣列的第一維是縱向座標,第二維才是橫向。並且都是從\(0\)開始索引計數的:
void work(string s){ for(int p=0;p<s.length();p++){ int num=s[p]-'0';//轉化成真實數字 int xst=num*4;//這個數字對應的base_1裡的位置起始點 for(int i=0;i<=4;i++){//遍歷這個數字對應的base_1裡的點 for(int j=xst;j<=xst+2;j++){ pict[i][j-xst+now]=base_1[i][j];//j-xst將[xst,xst+2]對映為[0,2],再加上now表示從now位置寫入畫布 } } for(int i=0;i<=4;i++) pict[i][now-1]='.';//補全一列空點 now+=4;//下一個寫入的位置 } }
輸出就比較簡單了:
void print(){//輸出
for(int i=0;i<=4;i++){
for(int j=0;j<=len*4;j++){//len*4表示預期畫布寬度(其實只要這個數字夠大就行,C++貌似會自動換行)
cout<<pict[i][j];//即使輸入的長度與原數字串長度不相等,它竟然也能正常工作!
}
cout<<endl;
}
}
總體AC程式碼:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char base_1[5][40]={
"XXX...X.XXX.XXX.X.X.XXX.XXX.XXX.XXX.XXX",
"X.X...X...X...X.X.X.X...X.....X.X.X.X.X",
"X.X...X.XXX.XXX.XXX.XXX.XXX...X.XXX.XXX",
"X.X...X.X.....X...X...X.X.X...X.X.X...X",
"XXX...X.XXX.XXX...X.XXX.XXX...X.XXX.XXX",
// 0 2 4 6
};
char pict[6][9999];//畫布,即題目中的"顯示屏"。
int now=0;//表示這個數字應該在畫布的第幾個位置寫入
int len;//字串長度
void work(string s){
for(int p=0;p<s.length();p++){
int num=s[p]-'0';//轉化成真實數字
int xst=num*4;//這個數字對應的base_1裡的位置起始點
for(int i=0;i<=4;i++){//遍歷這個數字對應的base_1裡的點
for(int j=xst;j<=xst+2;j++){
pict[i][j-xst+now]=base_1[i][j];//j-xst將[xst,xst+2]對映為[0,2],再加上now表示從now位置寫入畫布
}
}
for(int i=0;i<=4;i++)
pict[i][now-1]='.';//補全一列空點
now+=4;//下一個寫入的位置
}
}
void print(){//輸出
for(int i=0;i<=4;i++){
for(int j=0;j<=len*4;j++){//len*4表示預期畫布寬度(其實只要這個數字夠大就行,C++貌似會自動換行)
cout<<pict[i][j];//即使輸入的長度與原數字串長度不相等,它竟然也能正常工作!
}
cout<<endl;
}
}
int main(){
cin>>len;
string str;
cin>>str;
work(str);
print();
return 0;
}