Java教程

第七届蓝桥杯Java B组题解

本文主要是介绍第七届蓝桥杯Java B组题解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

A.煤球数目

题目描述

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

有一堆煤球,堆成三角棱锥形。具体: 第一层放 1个, 第二层 3个(排列成三角形), 第三层 6个(排列成三角形), 第四层 10个(排列成三角形), … 如果一共有 100层,共有多少个煤球?

题目分析

找规律,观察到第i层煤球数目为i*(i+1)/2

题解

171700
/**
 * @Description
 * @Author:PrinceHan
 * @CreateTime:2022/2/5 08:33
 */
public class Main {
    public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i * (i + 1) / 2;
        }
        System.out.println(sum);
    }
}

B.生日蜡烛

题目描述

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

某君从某年开始每年都举办一次生日 party,并且每次都要吹熄与年龄相同根数的蜡烛。

现在算起来,他一共吹熄了 236 根蜡烛。

请问,他从多少岁开始过生日 party 的?

请输出他开始过生日 party 的年龄数。

题目分析

可以先初始化蜡烛数组,在数组中找一段连续的区间和使和等于236。可以维护一个窗口,当和小于236时,滑动右窗口,当和大于236时,滑动左侧窗口,等于236时,输出左窗口的值,即为所求。

题解

26
/**
 * @Description
 * @Author:PrinceHan
 * @CreateTime:2022/2/5 08:39
 */
public class B {
    public static void main(String[] args) {
        int sum = 0;
        int[] arr = new int[101];
        for (int i = 1; i <= 100; i++) {
            arr[i] = i;
        }
        for (int i = 1, j = 1; i <= 100 && j <= 100; ) {
            if (sum < 236) sum += arr[j++];
            if (sum == 236) {
                System.out.println(i);
                System.exit(0);
            }
            if (sum > 236) {
                sum -= arr[i];
                i++;
            }
        }
    }
}

C.凑算式

题目描述

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

     B      DEF
A + --- + ------- = 10
     C      GHI

这个算式中 A ~ I 代表 0 ~ 9 的数字,不同的字母代表不同的数字。

比如: 6+8/3+952/7146+8/3+952/714 就是一种解法, 5+3/1+972/4865+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?

题目分析

本质上是一道求全排列的问题,用到了深搜,只是对数组的元素进行了一个处理。

题解

29
/**
 * @Description
 * @Author:PrinceHan
 * @CreateTime:2022/2/5 08:48
 */
public class C {
    static int[] nums = new int[10];
    static boolean[] vis = new boolean[10];
    static int ans;

    public static void main(String[] args) {
        dfs(1);
        System.out.println(ans);
    }

    public static void dfs(int step) {
        if (step == 10 && check(nums)) {
            ans++;
            return;
        }
        for (int i = 1; i < 10; i++) {
            if (!vis[i]) {
                nums[step] = i;
                vis[i] = true;
                dfs(step + 1);
                vis[i] = false;
            }
        }
    }

    public static boolean check(int[] a) {
        int num1 = a[3];
        int num2 = a[4] * 100 + a[5] * 10 + a[6];
        int num3 = a[7] * 100 + a[8] * 10 + a[9];
        if (a[1] * num1 * num3 + a[2] * num3 + num2 * num1 == 10 * num1 * num3) return true;
        return false;
    }
}

D.分小组

题目描述

本题为代码补全填空题。

9名运动员参加比赛,需要分3组进行预赛。 有哪些分组的方案呢?

我们标记运动员为 A,B,C,… I。

下面的程序列出了所有的分组方法。

源代码

import java.util.*;
public class Main
{
    public static String remain(int[] a)
    {
        String s = "";
        for(int i=0; i<a.length; i++){
            if(a[i] == 0) s += (char)(i+'A');
        }    
        return s;
    }
    
    public static void f(String s, int[] a)
    {
        for(int i=0; i<a.length; i++){
            if(a[i]==1) continue;
            a[i] = 1;
            for(int j=i+1; j<a.length; j++){
                if(a[j]==1) continue;
                a[j]=1;
                for(int k=j+1; k<a.length; k++){
                    if(a[k]==1) continue;
                    a[k]=1;
                    System.out.println(____________________________);
                    a[k]=0;
                }
                a[j]=0;
            }
            a[i] = 0;
        }
    }
    
    public static void main(String[] args)
    {
        int[] a = new int[9];        
        a[0] = 1;
        
        for(int b=1; b<a.length; b++){
            a[b] = 1;
            for(int c=b+1; c<a.length; c++){
                a[c] = 1;
                String s = "A" + (char)(b+'A') + (char)(c+'A');
                f(s,a);
                a[c] = 0;
            }
            a[b] = 0;
        }
    }
}

在这里插入图片描述

题目分析

本题是一道代码填空题,有一定的做题技巧。首先代码中给的函数或者是变量一定会用到,可以通过打断点,调试程序是怎么运行的。在main()方法得到的是前三个字母,并将s通过参数传递给f()方法,这里意识到可能会拼接字符串,f()方法是为了获得中间三位的字符串,通过remain()方法得到包含剩余字母的字符串,将字符串拼接,打印输出即可。

题解

System.out.println(s + " " + (char) (i + 'A') + (char) (j + 'A') + (char) (k + 'A') + " " + remain(a));

E.抽签

题目描述

本题为代码补全填空题,请将题目中给出的源代码补全。

X星球要派出一个 5 人组成的观察团前往 W 星。

其中:

A 国最多可以派出 4 人。

B 国最多可以派出 2 人。

C 国最多可以派出 2 人。

那么最终派往 W 星的观察团会有多少种国别的不同组合呢?

下面的程序解决了这个问题。 数组 a[] 中既是每个国家可以派出的最多的名额。 程序执行结果为:

DEFFF
CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF
....
(以下省略,总共101行)

下面的代码就是为了这个目的的,请仔细阅读源码,并填写划线部分缺少的代码。

源代码

import java.util.*;
public class Main
{
    public static void f(int[] a, int k, int n, String s)
    {
        if(k==a.length){ //考虑到了所有的国家
            if(n==0) System.out.println(s);//n==0说明取到了5个人
            return;
        }
        
        String s2 = s;//保存已经选择的组合
        for(int i=0; i<=a[k]; i++){
            ______________________;
            s2 += (char)(k+'A');
        }
    }
    
    public static void main(String[] args)
    {
        int[] a = {4,2,2,1,1,3};
        
        f(a,0,5,"");
    }
}

题目分析

观察f()方法,有出口,意识到可能要用到递归。观察到main()方法中f()方法传参k = 0,n = 5,递归结束条件为ka.length,n0则要让k增大,n减小,在代码填空处要完成这些操作。

for (int i = 0; i <= a[k]; i++) {
    f(a, k+1,n-i,s2);//k+1访问下一个国家,n-i表示从当前国家中减去选择的人数
    s2 += (char) (k + 'A');
}

F.方格填数

题目描述

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

如下的 10 个格子:

   +--+--+--+
   |  |  |  |
+--+--+--+--+
|  |  |  |  |
+--+--+--+--+
|  |  |  |
+--+--+--+

填入 0 ~ 9 的数字。要求:连续的两个数字不能相邻。 (左右、上下、对角都算相邻)

一共有多少种可能的填数方案?

题目分析

本质上是一道全排列,但要求连续的两个数字不相邻,不相邻指的是差的绝对值不等于1,判断一下即可。

题解

1580
/**
 * @Description
 * @Author:PrinceHan
 * @CreateTime:2022/2/6 09:41
 */
public class F {
    static int[] nums = new int[10];
    static boolean[] vis = new boolean[10];
    static int ans;

    public static void main(String[] args) {
        dfs(0);
        System.out.println(ans);
    }

    public static void dfs(int step) {
        if (step == 10 && check(nums)) {
            ans++;
            return;
        }
        for (int i = 0; i < 10; i++) {
            if (!vis[i]) {
                nums[step] = i;
                vis[i] = true;
                dfs(step + 1);
                vis[i] = false;
            }
        }
    }

    public static boolean check(int[] a) {
        return Math.abs(a[0] - a[1]) != 1 && Math.abs(a[1] - a[2]) != 1 && Math.abs(a[3] - a[4]) != 1 && Math.abs(a[4] - a[5]) != 1 && Math.abs(a[5] - a[6]) != 1 && Math.abs(a[7] - a[8]) != 1 && Math.abs(a[8] - a[9]) != 1 && Math.abs(a[0] - a[4]) != 1 && Math.abs(a[1] - a[5]) != 1 && Math.abs(a[2] - a[6]) != 1 && Math.abs(a[3] - a[7]) != 1 && Math.abs(a[4] - a[8]) != 1 && Math.abs(a[5] - a[9]) != 1 && Math.abs(a[0] - a[3]) != 1 && Math.abs(a[1] - a[4]) != 1 && Math.abs(a[2] - a[5]) != 1 && Math.abs(a[0] - a[5]) != 1 && Math.abs(a[1] - a[6]) != 1 && Math.abs(a[3] - a[8]) != 1 && Math.abs(a[4] - a[9]) != 1 && Math.abs(a[4] - a[7]) != 1 && Math.abs(a[5] - a[8]) != 1 && Math.abs(a[6] - a[9]) != 1;
    }
}

G.剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。

在这里插入图片描述

现在你要从中剪下 5张来,要求必须是连着的。

(仅仅连接一个角不算相连) 比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

在这里插入图片描述

在这里插入图片描述

请你计算,一共有多少种不同的剪取方法。

题目分析

一开始做的时候想着用dfs搜一下,但是运行起来方案数量比正确答案少,看了看题解发现用dfs无法解决“T”型方案。借鉴了B站上的题解,剪邮票。
从12个里面选择5个,可以初始化一个数组,长度为12,中有5个1,对这个数组进行全排列,再判断选取的是否联通,判断联通问题可以用dfs处理,在进行全排列时,要考虑全排列重复的情况,进行去重,在C++中有现成的全排列函数:

 #include <algorithm>
 bool next_permutation(iterator start,iterator end)

可以得到不重复的全排列,但在Java中没有全排列的方法,一般通过手写dfs来实现。

题解

116
/**
 * @Description
 * @Author:PrinceHan
 * @CreateTime:2022/2/6 10:20
 */
public class G {
    static int[] a = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};//邮票数组
    static int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
    static boolean[] vis = new boolean[12];
    static int ans;

    public static void main(String[] args) {
        int[] path = new int[12];
        f(0, path);
        System.out.println(ans);
    }

    static void dfs(int[][] g, int x, int y) {
        g[x][y] = 0;//将1的部分标记为0
        for (int i = 0; i < 4; i++) {
            int xx = x + dx[i];
            int yy = y + dy[i];
            if (in(xx, yy) && g[xx][yy] == 1) {
                dfs(g, xx, yy);
            }
        }
    }

    static boolean check(int[] path) {
    	//path数组可以看作是存放全排列结果的容器,下文中的path数组也是
        int[][] g = new int[3][4];//g即graph,表示选择的哪一块
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                if (path[i * 4 + j] == 1) g[i][j] = 1;//与下标对应上
                else g[i][j] = 0;
            }
        }
        int cnt = 0;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                if (g[i][j] == 1) {
                    dfs(g, i, j);//如果这块是选择的一块,从这一块开始深搜
                    cnt++;
                }
            }
        }
        return cnt == 1;//一次深搜证明联通
    }
    //全排列函数,path数组可以看作是存放全排列结果的容器
    static void f(int k, int path[]) {
        if (k == 12) {
            if (check(path)) ans++;
        }
        for (int i = 0; i < 12; i++) {
        //去重,如果选取了当前的,并且当前的与前一步的结果一样,但是前一步还没有选择,跳过这一步
            if (i > 0 && a[i] == a[i - 1] && !vis[i - 1]) continue;
            if (!vis[i]) {
                vis[i] = true;
                path[k] = a[i];
                f(k + 1, path);
                vis[i] = false;
            }
        }
    }

    static boolean in(int x, int y) {
        return x >= 0 && x < 3 && y >= 0 && y < 4;
    }
}

这篇关于第七届蓝桥杯Java B组题解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!