试题 D: 七段码
本题总分:10 分
【问题描述】
小蓝要用七段码数码管来表示一种特殊的文字。
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
例如: b 发光,其他二极管不发光可以用来表达一种字符。
例如: c 发光,其他二极管不发光可以用来表达一种字符。这种 方案与上 一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如: a, b, c, d, e 发光, f, g 不发光可以用来表达一种字符。
例如: b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光 的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
【思路】
深度优先搜索+状态压缩+HashSet唯一性
【Java代码】
package lanqiao2020;
import java.util.ArrayList;
import java.util.HashSet;
public class test {
//使用HashSet可以唯一性存储符合条件的数码管亮灭情况状态
static HashSet<Integer> set = new HashSet<>();
//使用邻接链表存储数码管连通情况
static ArrayList<Integer>[] list = new ArrayList[7];
public static void main(String[] args) {
//初始化连通情况
for(int i = 0; i < 7; i++) {
list[i] = new ArrayList<Integer>();
}
list[0].add(1);
list[0].add(5);
list[1].add(0);
list[1].add(6);
list[1].add(2);
list[2].add(1);
list[2].add(3);
list[2].add(6);
list[3].add(2);
list[3].add(4);
list[4].add(3);
list[4].add(5);
list[4].add(6);
list[5].add(0);
list[5].add(4);
list[5].add(6);
list[6].add(1);
list[6].add(2);
list[6].add(4);
list[6].add(5);
//以每个数码管作为起点(即在该数码管必须亮情况下)
for (int i = 0; i < 7; i++) {
set.add(1<<i); //单独亮也符合情况,所以存储进去
dfs(1, i, 1<<i); //深度优先搜索
}
System.out.println(set.size()); //因为唯一性,所以set中元素的个数即为符合条件的数码管亮灭状态的数量
}
//深度优先搜索,第一个参数代表当前亮了几个数码管,第二个参数代表当前最近亮起的数码管,第三个参数即为当前状态(如0000001代表0号数码管亮,其余不亮)
static void dfs(int total, int cur, int state) {
//最多亮起7个数码管
if (total == 7) {
return;
}
for (Integer item : list[cur]) {
if (!set.contains(state | (1<<item))) {
set.add(state | (1<<item));
}
dfs(total+1, item, state | (1<<item));
}
}
}
【结果】