蓝桥杯第十届真题第五题:七段码

原题:

题目描述
小蓝要用七段码数码管来表示一种特殊的文字。
七段码上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?

蓝桥杯第十届真题第五题:七段码_第1张图片

图示,这里的A只与F,B相连,B只与A,G,C相连,在这里我们要判断每个点亮着的时候,与它不连接的灯是否亮着,如果存在,就代表不成字符;

具体的思路是,深搜+存储;

这里的存储有多种方法,很多博主尝试并查集存储,因为每个点都连接着有点,使用并查集的话可以找到与它连接的点,从而找到没有连接的点。

但是这里我发现,使用单链表或许会更好?(绝不是博主看不懂并查集方法并且不愿意学习)

说开始就开始,具体的方法:我们把每一个点当成单链表的头,然后把每一个出点存储在它的下面,这就是为什么我的每一个字母后面跟着数字,数字代表这个位置;

那么我们来看一下对应关系:

                  A   B   C   D  E  F  G   

编号:       1   2   3   4   5   6   7

子个数:    2   3   3   2   3   3   4

子:           2   1   4   3   4   1   2

                  6   3   7   5   6   7   3

                       7   2        7   5   5

                                                6

通过此对应关系,我们可以把每个节点和他的子都存储起来,接下来就是我们的dfs;

dfs的可以把每个点的状态表示出来,我们可以用dfs把每个点是否点亮用0与1表示;这里我们用点小技巧代码如下:

for(int i=0;i<2;i++)
{
	st[k]=i;
	dfs(k+1);
}

st存储每个点的状态,0代表不亮,1代表亮,直接赋值i的话我么就不用打表了,这样通过dfs我们可以模拟出所有情况,接下来只需要对每种状态进行操作即可;

思路是:使用队列,循环存储第一个亮着的点,接着遍历这个点的所有子,将亮着的子加入队列,并且将子灭掉(赋值为0),进行重复循环,直到队列为空结束;

我们通过观察发现,只要能成为字符,那么通过一个点,一定可以遍历到所有亮着的点,所以我们找到第一个亮着的点,接着把这个点和它连着点,和与它连着的点连着的点...都灭掉,肯定的,只要成为字符,那么我们一定可以通过这步操作灭掉所有的点,但是如果不成字符,那么一定会有点不会被灭掉,我们加一层循环判断,只要有亮着的点就不成立即可;

具体代码:

#include
#include
#include
#include
using namespace std;
queueq;

const int N=50;
int h[10],e[N],ne[50],idx=0;//图的存储 
int st[10],stad[10];//st用来生成亮或者不亮,stad用来进行字符判断 
int n;

void add(int a,int b)
{
	e[idx]=b;
	ne[idx]=h[a];
	h[a]=idx++;
}

int ans=0;//存储答案 

void zh()
{
	for(int i=1;i<=n;i++)
		stad[i]=st[i];
}//复制操作 

void dfs(int k)
{
	if(k==n+1)//dfs结束的条件是我们遍历到了所有点的下一个点 
	{
		zh();//因为这一步要对我们的数组操作,我们必须另开一个一样的数组操作
		     //否则会导致原dfs数组出错 
		int k=-1;//通过k查找第一个亮着的点(其实只要是个亮着的点都可以) 
		for(int i=1;i<=n;i++)
		{
			if(stad[i]==1)
			{
				k=i;
				break;
			}
		}
		
		if(k==-1)
		return ;//全灭的情况,一定不成立; 
		
		
		q.push(k);//加入队列 
		stad[k]=0;//讲这个点灭掉 
		while(!q.empty())
		{
			int m=q.front();
			q.pop();
			for(int j=h[m];j!=-1;j=ne[j])
			{
				if(stad[e[j]]==1)//这步一定要加判断,因为我们只要亮着的点,否则所有点全加进去再循环会造成死循环 
				{
					q.push(e[j]);
					stad[e[j]]=0;
				}
			}
		}//遍历操作 
			
//		cout<>n;
	for(int i=1;i<=n;i++)
	{
		int m;
		cin>>m;
		for(int j=0;j>k;
			add(i,k);
		}
	}//初始化,这一步我们需要把预处理的值输入(填空题,只要答案就行) 
	
	
	dfs(1);//dfs 
	
//	for(int i=1;i<=n;i++)
//	{
//		cout<

完整代码如上,完结撒花;

你可能感兴趣的:(c++,蓝桥杯,算法,c++,c语言,蓝桥杯)