P5730 【深基5.例10】显示屏

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;
}
posted @ 2020-07-13 11:31  梦中霜雪梨花白  阅读(384)  评论(0编辑  收藏  举报