查并集大体上分为3部。
1、初始化
2、合并
3、查找
-
初始化就是将每一个点看成一个集合。
-
合并是把两个相关的点录入father数组。
-
查找就是给定一个数通过递归来找到他的根结点也就是所说的父节点。
一、题目
1.题目描述
小蓝要用七段码数码管来表示一种特殊的文字。
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是>连成一片的。
例如:b 发光,其他二极管不发光可以用来表达一种字符。
例如:c 发光,其他二极管不发光可以用来表达一种字符。
这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。
例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光的二极管没有连成一片。
2.提问
请问,小蓝可以用七段码数码管表达多少种不同的字符?
3.答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
二、题解思路
结合DFS + 查并集
详细解释请看代码块的注释,会比较形象
三、代码块
代码如下(示例):
package 七段码;
/**
* 一些声明信息
* Description: dfs+查并集
* date: 2022/4/6 19:37
* @author Haier
* @version 1.0
* @since JDK 1.8
*/public class Main {
static int[] father=new int[8];
static int[][] light=new int[8][8];//连通
static boolean[] islight=new boolean[8];//亮灯
static int acount;//计数
public static void main(String[] args) {
//a b c d e f g
//1 2 3 4 5 6 7
//连边建图,light[i][j] == 1表示第i段和第j段灯管相邻
//a-b a-f
light[1][2]=light[1][6]=1;
//b-a b-g b-c
light[2][1]=light[2][3]=light[2][7]=1;
//c-g c-d c-b
light[3][4]=light[3][7]=light[3][2]=1;
//d-e d-c
light[4][5]=light[4][3]=1;
//e-g e-f e-d
light[5][6]=light[5][7]=light[5][4]=1;
//f-g f-e f-a
light[6][7]=light[6][5]=light[6][1]=1;
dfs(1);
System.out.println(acount);
}
private static void dfs(int startIndex) {
//出口
if (startIndex==8){
//初始化每一个父节点
for (int i = 1; i < 8; i++) {
father[i]=i;
}
//判断是否在同一个集合
for (int i = 1; i <=7 ; i++) {
for (int j = 1; j <=7 ; j++) {
如果当前两盏相互连接的灯处于打开的状态则放在一个集合里
if (islight[i]&&islight[j]&&light[i][j]==1){
union(i,j);//合并
}
}
}
int ans=0;//记录“植物数” 通俗易懂
//寻找“植物”
for (int i = 1; i < 8; i++) {
if (father[i]==i&&islight[i]){
ans++;
}
}
//当有且仅有一种联通亮灯情况的时候才合法,这个时候才算数 避免没有连通算进去
if (ans==1) acount++;
return;
}
//下一个灯
islight[startIndex]=true;//打开i这个灯,继续开关下一个灯
dfs(startIndex+1);
islight[startIndex]=false;//关闭i这个灯,继续开关下一个灯
dfs(startIndex+1);
}
//合并 // TODO: 2022/4/6 合并模板
private static void union(int a,int b){
a=findFather(a);
b=findFather(b);
if (a!=b)
father[b]=a;
}
//找父节点 // TODO: 2022/4/6 找父节点模板
private static int findFather(int a){
if (a==father[a]) return a;
father[a]=findFather(father[a]);
return father[a];
}
}