2020 蓝桥杯真题 七段码Java 易懂暴力深搜非差并集

题目:
题目:

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

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

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

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

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

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

思路:

大体思路是这样
1.要求多少种不同的表达式,换一种说法a~g所有的灯排成一行,放进一个
一维数组(递归实现指数型枚举),每次从中选取人n个灯,选到的灯变亮,
不选的不亮,这样就把所有情况都包含进来,我们只需判断每一种情况是否
合法,和发则ans++;

2.为了更好的判断所有亮的灯是否联通,把原图转换成一下这种二维图
然后六个方向搜索就行了,哪六个呢:右下、左下、左上、右上、下两格、上两格;

3.注意并不是所有的灯都有以上这六种方向,看原图的灯,如果只有a和g这
两个灯亮了并不满足题意,因为在原图它们不相连,因此a、g、d这个一列
所搜的时候不会有六个方向只会有四个;


在这里插入图片描述
代码:

import java.util.Scanner;
public class 七段码 {
    static int N=7;
    static int ans=0;
    static int countdeng=0;//每一次深搜时亮灯的个数

    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        //把所有灯的情况全部判断出来,然后判断此时的情况是否合法
        //第一步深搜枚举
        int []arr=new int[8];
        int []vis=new int[8];
        dfs(arr,vis,1);

        System.out.println(ans);
    }
    static void dfs(int []arr,int []vis,int level){
        if(level>7){
            check(arr);
            return;
        }
        //一共就两种情况,一种是要当前这个灯亮,一种是不要,分别深搜就行
        vis[level]=1;
        arr[level]=1;
        dfs(vis,arr,level+1);
        vis[level]=0;
        arr[level]=0;
        dfs(vis,arr,level+1);
    }
    static void check(int []arr){
        //先把此时灯亮的情况,在表格中显示出来,如果某一个灯需要亮
        //在二维表格中它对应的数就为1;
        int [][]map=new int[6][4];
        int [][]tempmap=new int[6][4];
        //a
        map[1][2]=arr[1];
        //b
        map[2][3]=arr[2];
        //c
        map[4][3]=arr[3];
        //d
        map[5][2]=arr[4];
        //e
        map[4][1]=arr[5];
        //f
        map[2][1]=arr[6];
        //g
        map[3][2]=arr[7];

        //我们要看此时灯是否能连起来
        //可以还用深搜,先把所有的灯亮的个数记录起来
        //然后以其中一个亮点为起点,向其中六个方向深搜
        //每找到一个一个可以联通的点总的灯数就减去一
        //最后全部搜完后还剩一盏灯亮着就说明当前方案可行,反之则不行
        //找总共有多少盏灯亮着
        //所欲多次深搜要初始化
        countdeng=0;
        for(int i=1;i<=5;i++) {
            for (int j = 1; j <= 3; j++) {
                if (map[i][j] != 0)
                    countdeng++;
            }
        }
        //找到了所有灯之后,找一个亮灯的点,开始深搜
        int flag=0;//只需要找一个点深搜即可,搜一次后就全部停止
        for(int i=1;i<=5;i++){
            for(int j=1;j<=3;j++) {
                if (map[i][j] != 0) {
                    flag = 1;
                    check2(map,tempmap, i, j);
                    break;
                }
            }
            if (flag==1)
                break;
        }
        if(countdeng-1==0)
        {
        ans++;
        }
    }
    //能走的六个方向
    public static  int []xx={1,1,-1,-1,-2,2};//2和-2是因为原图中两个边上的相连也算 
                                             //转换成二维图就是加-2和加2
    public static  int []yy={-1,1,-1,1,0,0};


    static void check2(int [][]map,int [][]temp,int x,int y){
        temp[x][y]=1;//起始点也要标记下
        for(int i=0;i<6;i++){
            if(y==2&&i>=4){
                continue;//这里特判了a g d它们只有四个方向
            }
            //这一步很重要,因为中间的a,g,d按原图来是不能上下跳的,这样按原图来是不连续的
            //然后就是判断是否越界,是否已经找过,是否灯亮
            int tempx=x+xx[i];
            int tempy=y+yy[i];
            //看是否越界
            if(tempx>5||tempx<1)
                continue;
            if(tempy>3||tempy<1)
                continue;
            //是否找到过
            if(temp[tempx][tempy]!=0)
                continue;
            //判断这个点是否有
            if(map[tempx][tempy]==0)
                continue;
            if (map[tempx][tempy]==1) {
                temp[tempx][tempy] = 1;
                countdeng--;
                check2(map, temp, tempx, tempy);
            }
        }
        return ;
    }

}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值