第十一届蓝桥杯省赛(七段码)--排列组合/DFS的应用

6 篇文章 0 订阅
5 篇文章 0 订阅

【问题描述】
小蓝要用七段码数码管来表示一种特殊的文字。
在这里插入图片描述
七数码

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

【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

思路:
因为是道填空题,所以不用考虑算法的时间效率什么的,只要能得出答案就行,这里只是其中的一种解法。
这道题可以是典型的n个数中选m个DFS的应用的问题。这里可以试着把所有的选法(7选1,7选2…7选7)枚举出来,接着对所有的情况依次都判断一遍此时的情况是不是一个合法解,是的话总数就加一。
如何判断此时的序列是否是一个合法解,就是判断这个序列的第一个位置能否跑到此序列的其他所有点,简化成一个无向图的问题,判断下连通性。

无向图
这里用数字(1-7)代替了原本的字符(a-g),方便标记判断。例如某次n选m生成了一个序列(2,1,7,5),那就分别dfs(2,1),dfs(2,7),dfs(2,5),若都能走通就代表这是个合法情况,总次数加一。至于dfs的实现,就是纯基础走图了,不太懂的可以看下这篇文章这篇文章,嘿嘿。
代码如下:

#include <iostream>
#include <string.h>
using namespace std;
int map[10][10],book[105],s=0,flag=0;
int judge2(int a[],int x,int sum)
{
	int i;
	for(i=1;i<=sum;i++)
	{
		if(a[i]==x)
		return 1;
	}
	return 0;
}
void dfs(int x,int y,int b[],int sum)
{
	int i;
	if(x==y)
	{
		flag=1;
		return;
	}
	for(i=1;i<=7;i++)
	{
		if(book[i]==0)
		{
			if(map[x][i]==1&&judge2(b,i,sum))
			{
				book[i]=1;
				dfs(i,y,b,sum);
				book[i]=0;
			}
		}
	}
	return;
}
int judge(char a[],int sum)
{
	int i;
	if(sum==1)
	return 1;
	int b[10066];
	for(i=1;i<=sum;i++)
	{
		b[i]=a[i]-'a'+1;
	}
	book[b[1]]=0;
	for(i=2;i<=sum;i++)
	{
		flag=0;
		memset(book,0,sizeof(book));
		dfs(b[1],b[i],b,sum);
		if(flag==0)
		return 0;
	}
	return 1;
}
void combine(int n,int m,char a[],int b[],int M)
{
	int i,j;
	for(i=n;i>=m;i--)
	{
		b[m-1]=i-1;
		if(m>1)
		{
			combine(i-1,m-1,a,b,M);
		}
		else {
			char ch[10005],ans=0;
			for(j=M-1;j>=0;j--)
			{
				ch[++ans]=a[b[j]];
			}
			if(judge(ch,ans))
			s++;
		}
	}
	return;
}
int main()
{
	char a[10005]={'a','b','c','d','e','f','g'};
	int b[10005],i,n,m;
	map[1][2]=1;
	map[2][1]=1;
	map[2][3]=1;
	map[3][2]=1;
	map[3][4]=1;
	map[4][3]=1;
	map[4][5]=1;
	map[5][4]=1;
	map[5][6]=1;
	map[6][5]=1;
	map[6][1]=1;
	map[1][6]=1;
	map[2][7]=1;
	map[7][2]=1;
	map[3][7]=1;
	map[7][3]=1;
	map[5][7]=1;
	map[7][5]=1;
	map[6][7]=1;
	map[7][6]=1;
	//cin>>n>>m;
	n=7;
	//for(i=0;i<n;i++)
	//{
	//	cin>>a[i];
	//}
	for(i=1;i<=n;i++)
	{
		m=i;
		combine(n,m,a,b,m);
	}
	cout<<s<<endl;
	return 0;
}
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值