1 条题解

  • 0
    @ 2025-8-24 21:16:21

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar DFs_YYDS
    明年不拿绿勾就再也别换个签了 || 擅长的是线下物理单杀而不是对线||上帝给我关了一扇门,但是我把门炸掉了 || 毁灭你,与你何关?

    搬运于2025-08-24 21:16:20,当前版本为作者最后更新于2024-06-08 07:46:46,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题目传送门

    题目大意

    给你红绿灯在显示 nn 次数字时,亮了哪些数码管,问你这些数码管有没有常亮(即无论什么数字都会亮)或不亮(即无论什么数字都不亮)。

    方法一(不推荐)

    具体思路

    按照题意模拟。

    nn 条日志,对于每条日志,首先处理常亮的情况。如果显示这个数字不需要显示该数码管,但是数码管亮了,就说明它是常亮的。然后再处理不亮的情况,如果显示这个数字需要显示该数码管,但是数码管没亮,就说明它是不亮的,将每个数码管的情况用一个 ansans 数组存起来,最后输出即可。

    完整代码

    #include<bits/stdc++.h>//万能头。 
    using namespace std;
    char ans[10];//数码管的状态,由于题目中说常亮用大写X,不亮用小写x,没发现故障用-,所以用字符数组来表示。 
    string book[10]={"ABCDEF ","BC ","ABGED ","ABGCD ","FGBC ","AFGCD ","AFDECG ","ABC ","ABCDEFG ","ABCDFG "};//book[i]表示显示第i个数需要显示的数码管编号。 
    int main(){//主函数。 
    	int n;//n次记录。 
    	cin>>n;//输入n。 
    	for(int i=0;i<7;i++)ans[i]='-';//刚开始将7个数码管的状态初始化为-,没发现任何故障。 
    	while(n--){//循环n次。 
    		string s;//由于日志是由数字和字母组成的,中间又没有空格,所以用字符串存储比较方便。 
    		cin>>s;//输入字符串s。 
    		int x=s[0]-'0'/*本次记录的数字*/,len=s.size()/*字符串的长度*/;
    		//处理常亮的情况。 
    		for(int i=1;i<len;i++){//循环这次记录的字符串,注意从1开始,因为前面还有一位是数字。 
    			int flag=1;//是否损坏。
    			for(int j=0;book[x][j]!=' ';j++){//由于显示每个数字需要的数码管不一样,所以统一最后有一个空格。 
    				if(book[x][j]==s[i]){//如果这个数码管本来就需要亮。 
    					flag=0;//没有损坏。 
    					break;//直接跳出循环,减少时间。 
    				}
    			}
    			if(flag)/*如果这个数码管不需要亮,但它亮了*/ans[s[i]-'A']='X';//这个数码管的状态就是常亮。 
    		}
    		//处理不亮的情况。 
    		for(int i=0;book[x][i]!=' ';i++){//循环显示x需要的数码管,遇到空格结束。 
    			int flag=1;//是否损坏。 
    			for(int j=1;j<len;j++){//循环日志中记录的亮的数码管,注意从1开始。 
    				if(book[x][i]==s[j]){//如果这个数码管在记录中确实亮了。 
    					flag=0;//没有损坏。 
    					break;//跳出循环。 
    				}
    			}
    			if(flag)/*如果这个数码管需要亮,但它没亮*/ans[book[x][i]-'A']='x';//这个数码管的状态就是不亮。 
    		}
    	}
    	for(int i=0;i<7;i++)cout<<ans[i];//输出ans数组。 
    	return 0;//好习惯。 
    }
    

    但是代码未免有些太长了,怎么缩短呢?

    方法二(推荐)

    具体思路

    方法一代码长的原因在于,用了两个循环双重循环分别处理常亮和不亮的情况,如果我们将常亮和不亮在同一个循环中一起处理,代码就会缩短很多。

    参考方法一,使用数组把显示每个数字需要亮的数码管存起来。但是跟方法一不一样的是,我们用的是 int 的二维数组(bool 也行)来存。booki,jbook_{i,j} 表示在显示数字 ii 时第 jj 个数码管是否需要亮,如果是 11 表示需要亮,如果是 00 表示不需要亮。

    同样,在 nn 个日志中。先建一个数组 aaaia_i 表示第 ii 个数码管是否亮了。然后循环每个数码管,如果 aja_j11bookx,jbook_{x,j}00,也就是说第 jj 个数码管不应该亮但是亮了,这个数码管就是常亮的;如果bookx,jbook_{x,j}11aja_j00,也就是说第 jj 个数码管应该亮但是没亮,这个数码管就是不亮的,将状态存入答案数组 ansans 中。

    这样,我们就将两个循环缩减为一个循环,大大的减少了代码量。

    完整代码

    #include<bits/stdc++.h>
    using namespace std;
    char ans[10];//答案数组。 
    int book[10][7]={1,1,1,1,1,1,0,
    				0,1,1,0,0,0,0,
    				1,1,0,1,1,0,1,
    				1,1,1,1,0,0,1,
    				0,1,1,0,0,1,1,
    				1,0,1,1,0,1,1,
    				1,0,1,1,1,1,1,
    				1,1,1,0,0,0,0,
    				1,1,1,1,1,1,1,
    				1,1,1,1,0,1,1,};
    int main(){
    	int n;
    	cin>>n;
    	for(int i=0;i<7;i++)ans[i]='-';//初始化。 
    	for(int i=0;i<n;i++){
    		string s;
    		cin>>s;
    		int x=s[0]-'0',len=s.size(); 
    		int a[10];//实际上a数组开到7就行了,这里开10保险一点。 
    		for(int j=0;j<7;j++)a[j]=0;//在循环内定义数组要先全部初始化为0。 
    		for(int j=1;j<len;j++)a[s[j]-'A']=1;//这个数码管亮了。 
    		for(int j=0;j<7;j++){
    			if(a[j]==1&&book[x][j]==0)ans[j]='X';//如果这个数码管亮了但是实际上不应该亮,这个数码管就是常亮的。 
    			if(a[j]==0&&book[x][j]==1)ans[j]='x';//如果这个数码管没亮但是实际上应该亮,这个数码管就是不亮的。 
    		}
    	}
    	for(int i=0;i<7;i++)cout<<ans[i];//输出答案数组。 
    	return 0;//华丽结束。 
    }
    

    如果你还觉得长是因为 bookbook 数组的原因,我们将 bookbook 数组放到一行,就不觉得长了。

    最终完整代码

    #include<bits/stdc++.h>
    using namespace std;
    char ans[10];//答案数组。 
    int book[10][7]={1,1,1,1,1,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,1,1,1,0,0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,};
    int main(){
    	int n;
    	cin>>n;
    	for(int i=0;i<7;i++)ans[i]='-';//初始化。 
    	for(int i=0;i<n;i++){
    		string s;
    		cin>>s;
    		int x=s[0]-'0',len=s.size(); 
    		int a[10];//实际上a数组开到7就行了,这里开10保险一点。 
    		for(int j=0;j<7;j++)a[j]=0;//在循环内定义数组要先全部初始化为0。 
    		for(int j=1;j<len;j++)a[s[j]-'A']=1;//这个数码管亮了。 
    		for(int j=0;j<7;j++){
    			if(a[j]==1&&book[x][j]==0)ans[j]='X';//如果这个数码管亮了但是实际上不应该亮,这个数码管就是常亮的。 
    			if(a[j]==0&&book[x][j]==1)ans[j]='x';//如果这个数码管没亮但是实际上应该亮,这个数码管就是不亮的。 
    		}
    	}
    	for(int i=0;i<7;i++)cout<<ans[i];//输出答案数组。 
    	return 0;//完结撒花! 
    }
    
    • 1

    信息

    ID
    10321
    时间
    1000ms
    内存
    512MiB
    难度
    2
    标签
    递交数
    0
    已通过
    0
    上传者