蓝桥杯——七段码(JAVA)

文章讲述了如何使用七段码数码管来表示特殊文字,通过建立并查集和使用深度优先搜索算法,计算出所有连成一片的发光二极管组合,以确定可表达的不同字符数量。
摘要由CSDN通过智能技术生成

题目:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝要用七段码数码管来表示一种特殊的文字。

上图给出了七段码数码管的一个图示,数码管中一共有 77 段可以发光的二 极管,分别标记为 a,b,c,d,e,f,g。

小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符 的表达时,要求所有发光的二极管是连成一片的。

例如:b 发光,其他二极管不发光可以用来表达一种字符。

例如 c 发光,其他二极管不发光可以用来表达一种字符。这种方案与上 一行的方案可以用来表示不同的字符,尽管看上去比较相似。

例如:a,b,c,d,e 发光,f,g 不发光可以用来表达一种字符。

例如:b,f 发光,其他二极管不发光则不能用来表达一种字符,因为发光 的二极管没有连成一片。

请问,小蓝可以用七段码数码管表达多少种不同的字符?

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

 代码:

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    static int count = 0;//有一种情况就加一
    static int [][] e = new int[10][10];//存放i,j两边是否相邻1-7:a-g
    static int[] f = new int[10];//用来存放并查集的父亲
    static boolean[] st = new boolean[10];//用来判断该边亮灭情况

   
    public static void main(String[] args) {
        e[1][2]=e[1][6]=1;//表示相邻
        e[2][1]=e[2][7]=e[2][3]=1;
        e[3][2]=e[3][7]=e[3][4]=1;
        e[4][3]=e[4][5]=1;
        e[5][7]=e[5][6]=e[5][4]=1;
        e[6][5]=e[6][7]=e[6][1]=1;
        e[7][2]=e[7][3]=e[7][5]=e[7][6]=1;
        dfs(1);
        System.out.println(count);
    }
    //用并查集的find找该点的父亲
    public static int find(int i){
        if(f[i]==i){
            return i;
        }
        return f[i] = find(f[i]);
    }

    //用dfs搜索
    public static void dfs(int d){
        //终止条件
        if(d > 7 ){
            //先初始化各点的父亲(并查集)
            for (int i = 1; i <= 7; i++) {//从下标为1开始到下标为7的数字,初始化他们对应的父亲
                f[i] = i;
            }
            //进行深度优先搜索(需要用到两套嵌套循环)寻找最终父亲。
            for (int i = 1; i <= 7; i++) {
                for (int j = 1; j <= 7; j++) {
                    //判断该二极管发光且相邻,则合并
                    if((e[i][j] == 1) && (st[i] ==true) &&(st[j] ==true)){
                        //取出他们当前的父亲
                        int fx = find(i);
                        int fy = find(j);
                        //若这两个人的父亲不相等,则合并
                        if(fx!=fy){
                            f[fx] = fy;
                        }
                    }
                }
            }
            int k = 0;//用来判断该次dfs中有多少个由边组成的集合(也就是有几个父亲)
            for (int i = 1; i <= 7 ; i++) {
                //该边亮且父亲是自己。
                if(st[i] && f[i] == i)k++;
            }
            //则表明该只有一个集合(所有亮的边最终父亲相同)
            if(k==1)count++;
            return ;
        }


        //打开第d个二极管
        st[d] = true;
        dfs(d+1);
        //关闭了第d个二极管
        st[d] = false;
        dfs(d+1);

    }
}

思路:先将灯管全部打开,然后逐步关闭,遍历所有可能的情况,然后每一种情况我们先设他的父亲为自己,然后如果两边相邻且都亮但父亲不相同,则将其合并此时他们就是同一个父亲(可以理解为是一家人),然后搜索完后进行比较如果所有亮的边属于一家则符合条件情况+1,如果不是一家说明中间有断开的地方则不符合条件跳过。

举个例子:假设a,b,f亮则经过搜索后父亲都为f,则他们是一家人也就是说三边相连符合条件。

如果a,b,f,d亮则abf父亲是f,d的父亲还是自己,则有两家人两家之间不相连不符合条件。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值