蓝桥杯:七段码
题目描述:
小蓝要用七段码数码管来表示一种特殊的文字。
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二
极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符
的表达时,要求所有发光的二极管是连成一片的。
例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上
一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光
的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?
答案:80
思路:
(觉得我啰嗦的可以直接看代码,有详细注释,还是挺好理解的)
大体思路并不难,分成两部分:一部分是遍历所有情况,第二部分是检查某种情况下是否连通。遍历比较简单,难点就在于如何检查连通。可以用并查集,不过我看别人弄的也挺复杂的,就没用并查集。(虽然我写的也挺复杂,,)
方便起见,把a,b,c,d,e,f这七段转换成0,1,2,3,4,5,6。像这样:
可以用字符串数组来保存连通的情况,比如str[1]=“026”。
用数组表示每个边的亮灭情况,索引代表边,1代表亮,0代表灭。
string str[7];
int arr[7] = { 0, 0, 0, 0, 0, 0, 0 };
void init()
{
str[0] = "15";
str[1] = "026";
str[2] = "136";
str[3] = "24";
str[4] = "356";
str[5] = "046";
str[6] = "1245";
}
然后怎么判断连通呢?我最初(其实不是)想的是:遍历 arr,保存所有值为 1 的索引到 v 中,然后再遍历v中的每一个索引i,在其余值为1的索引所对应的 str 中找 i,如果其中有一个找到,就说明整个是连通的,如果都没有找到,就是不连通的。
这么想乍看没什么问题,但是运行结果是83。说明还有情况没有考虑到。我对着所有判断为连通的字符串一个一个找,终于发现了其他情况。就是0 1 亮,3 4灭。这种情况会被判断为连通。
这种情况的特征是:有多个边只被找到了一次。而正常连通的情况下,最多只会有两个边只被找到一次。按照这种思路修改代码,终于对了。
感想: 有我思考+写代码+调试的时间都够我一个一个数数5遍以上了,总共也就不超过128种,考试遇到这种填空题完全可以一个一个地数,不放心还能多数几遍,写代码很容易漏掉某些情况,反而容易错。。。。
完整代码:
#include <bits/stdc++.h>
using namespace std;
string str[7]; //保存与第i段连通的边
int arr[7] = {0, 0, 0, 0, 0, 0, 0}; //表示每段的亮灭,1表示亮,0表示灭
void init() //初始化str
{
str[0] = "15";
str[1] = "026";
str[2] = "136";
str[3] = "24";
str[4] = "356";
str[5] = "046";
str[6] = "1245";
}
bool check() //检查arr确定是否连通
{
string s; //用来保存arr中值为1的所有索引
for (int i = 0; i < 7; i++) //遍历arr
{
if (arr[i] == 1)
{
s.append(to_string(i));
}
}
if (s.length() == 0)
return false;
if (s.length() == 1)
return true;
vector<int> v; //保存每个边被找到的次数
for (int i = 0; i < s.length(); i++)
{
int num = 0; //用来保存第i个边被找到的次数
for (int j = 0; j < s.length(); j++)
{
if (i == j)
continue;
if (str[s[j] - '0'].find(to_string(s[i] - '0')) != string::npos) //如果找到
{
num++;
}
}
if (num == 0)
return false;
v.push_back(num);
}
int count = 0; //被找到次数为1的边的个数
for (auto i : v)
{
if (i == 1)
count++;
}
if (count > 2)
return false;
return true;
}
string toString(int n) //十进制转成7位二进制字符串
{
string s;
for (int i = 0; i < 7; i++)
{
s = to_string(n & 1) + s;
n = n >> 1;
}
return s;
}
int fun()
{
init();
int ans = 0;
for (int i = 0; i < 128; i++) //通过二进制从0加到128遍历所有情况
{
string s = toString(i);
for (int j = 0; j < 7; j++)
{
arr[j] = s[j] - '0';
}
if (check())
{
++ans;
}
}
return ans;
}
int main()
{
cout << fun() << endl;
return 0;
}