七段码
小蓝要用七段码数码管来表示一种特殊的文字。
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
-
例如:b 发光,其他二极管不发光可以用来表达一种字符。
-
例如:c 发光,其他二极管不发光可以用来表达一种字符。
这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。
-
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
-
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?
答案
80
思路
考场上脑抽了,这一看就是图的题,就想着用Map + List建图,折腾了半个小时,发现这是无向图,然后绝望了,在草稿纸上推了一下,乱填了个60…
后面发现其实很简单,暴力就完了,填空题不求算法有多么好,只要能得到正确答案就行。虽然参加的是Java组的,但后面敲的是C++的解析,凑合着看吧~差不多的。吐槽考场辣鸡Eclipse疯狂报错,提供的是JDK1.8却只能用JDK1.4编译气死了。
吐槽完了,说一下下面代码的思路:
- 首先初始化建图(邻接表有点麻烦,邻接矩阵真香!)
- 爆搜路径长度1 - 7的所有对应的图的路径
- 检查路径是不是连通的(DFS、并查集都可)
- 输出满足条件的路径个数
===== 21.02.19 update 并查集 =====
DFS + 并查集
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
using std::string;
using std::vector;
// 七段码所有亮灯情况的存储容器
vector<string> candidate;
// 邻接矩阵存储,真香
int graph[7][7];
// 基础并查集
struct DisjointSet {
int* father;
explicit DisjointSet(int n) {
father = new int[n];
for (int i = 0; i < n; i++) {
father[i] = i;
}
}
// 找爸爸
int findRoot(int x) {
return father[x] == x ? x : father[x] = findRoot(father[x]);
}
// 合并
bool merge(int x, int y) {
int root_x = findRoot(x);
int root_y = findRoot(y);
if (root_x != root_y) {
father[root_x] = root_y;
}
return root_x != root_y;
}
};
/**
* 邻接矩阵初始化,1 代表连通
*/
void init() {
// a : 0, b : 1, c : 2
// d : 3, e : 4, f : 5, g : 6
memset(graph, 0, sizeof(graph));
// connect with 'a'
graph[0][1] = graph[0][5] = 1;
// connect with 'b'
graph[1][0] = graph[1][2] = graph[1][6] = 1;
// connect with 'c'
graph