蓝桥杯2020年第十一届javaB组省赛

蓝桥杯2020年第十一届javaB组省赛

A:门牌制作

在这里插入图片描述

思路:判断1-2020每个数有多少个2即可,代码很容易实现

答案:624

public class A门牌制作 {
    public static void main(String[] args) {
        int res = 0;
        for (int i = 1; i <= 2020; i++) {
            int j = i;
            while (j > 0) {
                if ((j % 10) == 2) { //判断个位是否为2
                    res++;
                }
                j /= 10;//将个位去掉继续判断
            }
        }
        System.out.println(res);
    }
}

B:寻找2020

在这里插入图片描述

思路:遍历每个位置,然后分三个方向去走

答案:16520

public class B寻找2020 {
    public static void main(String[] args) throws FileNotFoundException {
        int[][] arr = input();//读取文件操作
        int res = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                //1.先拿到每一个元素
                if (arr[i][j] == 0) continue;//如果是0就跳过
                //2.如果是2就分三路去搜索
                if (j + 3 < arr[i].length && arr[i][j+1] == 0 &&
                        arr[i][j+2] == 2 && arr[i][j+3] == 0) {
                    res++;
                }//向右
                if (i + 3 < arr.length && arr[i+1][j] == 0 &&
                        arr[i+2][j] == 2 && arr[i+3][j] == 0) {
                    res++;
                }//向下
                if (i + 3 < arr.length && j + 3 < arr[i].length &&
                        arr[i+1][j+1] == 0 && arr[i+2][j+2] == 2 && arr[i+3][j+3] == 0) {
                    res++;
                }//向右下侧
            }
        }
        System.out.println(res);

    }
    private static int[][] input() throws FileNotFoundException {
        FileInputStream fis = new FileInputStream(new File("D:\\workspace_idea\\javaSenior\\leetcode\\2020.txt"));
        Scanner sc = new Scanner(fis);
        List<String> list = new ArrayList<>();
        while (sc.hasNext()) {
            String s = sc.nextLine();
            list.add(s);
        }
        int[][] arr = new int[list.size()][list.get(0).length()];
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list.get(i).length(); j++) {
                arr[i][j] = list.get(i).charAt(j) - 48;
            }
        }
        return arr;
    }
}

C:蛇形填数

在这里插入图片描述

思路:

  • 找规律可以发现,n行n列的元素=(2 * n - 1行1列的元素 + 1行2 * n - 1列的元素) / 2 ,所以题目转化为找到这两个位置的元素。
  • 第一行和第一列的元素很有特点,比如第2行第1列的元素是1+2=3;第1行第3列的元素是1+2+3=6;依次类推。如果n是奇数,则1+2+…+n就是第1行第n列的元素;如果n是偶数,则1+2+…+n就是第n行第1列的元素;
  • 所以本题找第39行第1列的数 和 第1行第39列的数,然后求中间数。第39行第1列的数就是第38行第1列的数+1,最终就是要求(1+2+…+38+1 + 1+2+…+39) / 2;

答案:761 在网上看到有推出的公式直接代入,我数学能力表示搞不定。。

public class C蛇形填数 {
    public static void main(String[] args) {
        int a = 0, b = 0;
        for (int i = 1; i <= 38; i++) {
            a += i;
            b += i;
        }
        a += 39;
        b += 1;
        int res = (a + b) / 2;
        System.out.println(res);
    }
}

D:七段码

在这里插入图片描述

思路:

  • 利用二维数组表示图,将每个数码管之间的连接关系记录下来。
  • 将所有可能的发光组合全部都拿到,然后利用set加上排序起到去重的效果
  • 然后根据关系图来判断是否符合要求

答案:80

public class D七段码 {
    static Set<String> set = new HashSet<>();
    public static void main(String[] args) {
        int[][] map = new int[7][7];
        init(map);//1.初始化七段码的关系图
        //2.将所有开灯的组合放在set
        for (int i = 1; i <= 7; i++) {
            combination("abcdefg".toCharArray(),0, i);
        }
        //3.然后结合关系图判断是否符合要求
        int res = check(map);
        System.out.println(res);
    }

    private static int check(int[][] map) {
        int res = 0;
        for (String s : set) {
            boolean flag1 = true;//表示s是否符合要求,符合要求表示s可以连通起来
            //判断连通的操作,先选出一个字符c,加入set,然后每一轮遍历s,将所有与c连接的字符加入set,
            // 直到有一轮没有任何字符加入set,就表示不连通;如果全部加入了,就表示连通
            Set<Character> set = new HashSet<>();
            set.add(s.charAt(0));
            while (set.size() < s.length()) { //当全部加入了set,就表示连通,就退出循环
                boolean flag2 = false;//表示这一轮是否有字符加入set
                for (int i = 1; i < s.length(); i++) {
                    if (set.contains(s.charAt(i))) {
                        continue;
                    }
                    for (char c : set) {
                        if (map[s.charAt(i) - 97][c - 97] == 1) {
                            set.add(s.charAt(i));
                            flag2 = true;
                            break;
                        }
                    }
                }
                if (!flag2) {
                    flag1 = false;
                    break;
                }
            }
            if (flag1) {
                res++;
            }
        }
        return res;
    }

    private static void combination(char[] c, int k, int n) {
        if (k == n) {
            String s = new String(c, 0, n);
            //存放进去之前,将s按照字典序排序,为了将   ab  ba 这种情况合并成同一种结果
            char[] chars = s.toCharArray();
            Arrays.sort(chars);
            set.add(new String(chars));
        }
        for (int i = k; i < c.length; i++) {
            swap(c, i, k);
            combination(c, k+1, n);
            swap(c, i, k);
        }
    }

    private static void swap(char[] c, int i, int j) {
        char temp = c[i];
        c[i] = c[j];
        c[j] = temp;
    }

    private static void init(int[][] map) {
        for (int i = 1; i < map.length - 1; i++) {
            map[i][i-1] = 1;
            map[i][i+1] = 1;
            map[i][i] = 1;
        }
        map[0][1] = 1; map[0][5] = 1; map[1][6] = 1;map[2][6] = 1;
        map[4][6] = 1; map[5][0] = 1;map[6][1] = 1; map[6][2] = 1;
        map[6][4] = 1; map[6][5] = 1;
    }
}

E:排序

在这里插入图片描述

思路:

  • 因为要求最短,所以可以先假设字符串完全逆序 如 cba这样,这样的字符串长度n和交换次数c的关系 c = n * (n - 1) / 2,其实就是求了 1 + 2 + … + n - 1。
  • 找到正好比100次大的c,就是n=15时,c=105。
  • 因为要字典序最小,所以就将第一个字符和c-100位置的字符交换位置即可

答案: jonmlkihgfedcba

public class E排序 {
    public static void main(String[] args) {
        int c = 0;
        int n;
        for (n = 1; n < 100; n++) {
            c += n - 1;
            if (c >= 100) {
                break;
            }
        }
        System.out.println("c = " + c);
        System.out.println("b = " + n);
        
    }
}

F:成绩分析

在这里插入图片描述
在这里插入图片描述

思路:直接比较就行了,比较简单

public class F成绩分析 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        double sum = 0;
        int max = 0; int min = Integer.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            int num = sc.nextInt();
            max = Math.max(max, num);
            min = Math.min(min, num);
            sum += num;
        }
        System.out.println("max = " + max);
        System.out.println("min = " + min);
        System.out.println("average = " + String.format("%.2f",sum / n));
    }
}

G:单词分析

在这里插入图片描述
在这里插入图片描述

思路:也比较简单,使用Map或者数组,只要把每个字符出现的次数记录下来就行了。

public class G单词分析 {
    public static void main(String[] args) {
        int[] time = new int[26];//因为只有小写字母,所以26的长度就可以了
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        for (int i = 0; i < s.length(); i++) {
            time[s.charAt(i) - 97]++;
        }
        //找到出现最多的字符就行了
        char c = s.charAt(0); int t = 0;
        for (int i = 0; i < s.length(); i++) {
            int tt = time[s.charAt(i) - 97];
            if (tt > t) {
                c = s.charAt(i);
                t = tt;
            }
        }
        System.out.println(c);
        System.out.println(t);
    }
}

H:数字三角形

在这里插入图片描述
在这里插入图片描述

思路:

  • 定义一个二维数组dp, dp(i)(j)表示走到i,j位置可以加到的最大的值。
  • 因为要求向左下和向右下的次数相差不能超过1,所以经过推导,当层数n是奇数时,最终加和操作只能走到(n)(n/2)位置;当n是偶数时,能走到(n)(n/2)和(n)(n/2+1)位置,结果取dp数组中两者较大值即可。
public class H数字三角形 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[][] dp = new int[n+1][n+1];//下标为0的区域不放元素,方便理解,也方便后面代码书写,否则-1下标很难处理
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                dp[i][j] = sc.nextInt();//用题目数据给数组赋值。
                dp[i][j] += Math.max(dp[i-1][j], dp[i-1][j-1]);//dp操作,
                //dp存的是加和操作到这的最大值,而[i][j]位置的最大值是它左上方和右上方的最大值递推过来的。
            }
        }
        int res = (n & 1) == 1 ? dp[n][n/2+1] : Math.max(dp[n][n/2], dp[n][n/2+1]);
        System.out.println(res);
    }
}

I:子串分值和

在这里插入图片描述

思路:两层循环,使用set来动态获取不同字符的个数

public class I子串分值和 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        long res = 0;
        for (int i = 0; i < s.length(); i++) {
            Set<Character> set = new HashSet<>();//每一轮用一个set,每加一个元素,记录一次不同字符的个数
            for (int j = i; j < s.length(); j++) {
                set.add(s.charAt(j));
                res += set.size();
            }
        }
        System.out.println(res);
    }
}

J:装饰珠

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路:

  • 首先整理数据
    1. 猎人有6件装备,所以需要一个长度为6的数组存放装备。
    2. 每一个装备都有自己的N个装饰孔,这里可以选择封装成装备类,类里有一个长度为N整型数组存放每个装饰孔的等级。
    3. 装饰珠封装成类,属性有等级(int),上限数量(int),价值(int[],长度就是上限数量),共有M个装饰珠,外面定义一个数组存放即可。
  • 遍历每个装备,因为总的价值不同装备之间并无牵连,所以只需要每个装备都是最高价值就能解决
  • 遍历装备的每个孔,枚举出所有对装饰珠的选,结果放在一个长度为M的数组,表示对第i个装饰珠选择了几次;然后根据装饰珠类中的价值数组,算出价值。枚举得到最终结果。

暂时没做出来。。。

参考文章:

https://blog.csdn.net/qq_45566354/article/details/109142062

https://blog.csdn.net/qq_43652327/article/details/109138697

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值