2019 第十届蓝桥杯 Java B组 赛后总结
作为一名大三学生,在蓝桥杯 java 比赛中这是我参与的第一场竞赛同时也是最后一次机会(因为大四时可能没有时间准备)。报名参加的是 Java B 组的比赛整体来说赛事流程进展顺利作为首次参赛者在仅有的四个小时里感到时间稍显不足(并带有幽默感)。然而在整个比赛中是以尝试性质的态度加入的无需多言在此次之后我会撰写我的赛后总结报告由于个人能力有限请作为参考意见
- 第一题 分组
问题描述
问题描述

这道题是从20名选手中选拔5人参赛。难度适中,并且有一些需要注意的地方。这道题目主要作为热身练习。我的答案是490.-
- 第二题 子串
问题描述
问题描述
这道题相对来说并不复杂;可以通过StringBuffer的subString方法获取所需子字符串;然后将其放入HashSet中进行去重操作;最后 HashSet 的大小减一即为答案。至于为什么要减一的问题我也不是很清楚;不过通过测试题目中的实例以及自己编写的案例发现结果应为集合大小减一。
import java.util.HashSet;
public class _02子串 {
public static void main(String[] args) {
StringBuffer s = new StringBuffer("0100110001010001");
HashSet<String> set = new HashSet<String>();
// 双重循环,子串的头是s的第i个,尾是s的第j个
for (int i = 0; i <= s.length(); i++) {
for (int j = i; j <= s.length(); j++) {
String str = s.substring(i, j);
set.add(str);
}
}
System.out.println(set.size() - 1);
}
}

我最后算的答案是 100
问题描述
问题描述
这道题给我的第一印象是大数BigInteger,因为这道题类似于2018年java B组 复数幂的那道题,我做过所以印象特别深刻。这个数列类似于斐波拉契数列,但是如果用整型或者长整型数值肯定会爆。所以我一开始用大数写的,但是了十来分钟都没有出答案我就改个思路了。
第二个思路是:既然题目只要求第20190324项的最后4位数字,所以我就把每一项都求余10000,。因为加法是向前进位的,所以后取余对后四位没影响。
代码如下:
public class _03数列求值 {
public static void main(String[] args) {
int[] a = new int[20190324];
a[0] = 1;
a[1] = 1;
a[2] = 1;
for (int i = 3; i < a.length; i++) {
a[i] = (a[i - 1] + a[i - 2] + a[i - 3]) % 10000;
}
System.out.println(a[a.length-1]);
}
}

我的答案是 4659
**
问题描述
这道题是思路很简单,暴力解!写三个for循环,然后再写一个check方法,检查正整数里是否包含2或者4,把解出来的结果除以6就是正确答案,为什么要除以6呢?因为暴力解出来的答案是所有解的数量。题目中说了“交换 3 个整数的顺序被视为同一种方法”,三个整数交换顺序,那就成了三个数字的全排列问题了,全排列类型有6中,所以结果要除以6。
但是后来我发现事情不简单了。三个for循环,时间复杂度是2019 2019 2019,一个程序算出来得十来二十分钟。所以我改成了两个for循环。优化后,答案两秒钟就出来了!
代码如下:
public class _04数的分解 {
static int ans = 0;
public static void main(String[] args) {
for (int a = 1; a < 2019; a++) {
for (int b = 1; b < 2019; b++) {
int c = 2019 - a - b;
if (c > 0 && check(a) && check(b) && check(c)) {
ans++;
}
}
}
System.out.println(ans/6);
}
private static boolean check(int A) {
// 把要检验的数字转化成字符串
String s = A + "";
for (int i = 0; i < s.length(); i++) {
// 逐个字符检查是否含有2或4
if (s.charAt(i) == '2' || s.charAt(i) == '4')
return false;
}
return true;
}
}

我最后算出来的答案是 40935
接下来难度要逐步增加了!请做好心理准备!
**
问题描述
老直白地说啊!当我看到这个问题的时候就像喝了一大口冰镇可乐——兴奋得像是个活蹦乱跳的小机器!毕竟我已经做了无数道蓝桥杯题目呢!但一看到这道题就想到用深搜算法来解绝对不是什么新鲜事啦!然而等深入研究才发现自己当初太草率啦。。。。
当时我的想法就是:运用深度优先搜索(DFS)与回溯法相结合的方式,在到达终点时记录下最小步数以及路径信息。
public class _05迷宫 {
static int ans = 0;
static String res = "";
static int[][] mg;
static int max;
public static void main(String[] args) {
String[] s = { "01010101001011001001010110010110100100001000101010",
"00001000100000101010010000100000001001100110100101",
"01111011010010001000001101001011100011000000010000",
"01000000001010100011010000101000001010101011001011",
"00011111000000101000010010100010100000101100000000",
"11001000110101000010101100011010011010101011110111",
"00011011010101001001001010000001000101001110000000",
"10100000101000100110101010111110011000010000111010",
"00111000001010100001100010000001000101001100001001",
"11000110100001110010001001010101010101010001101000",
"00010000100100000101001010101110100010101010000101",
"11100100101001001000010000010101010100100100010100",
"00000010000000101011001111010001100000101010100011",
"10101010011100001000011000010110011110110100001000",
"10101010100001101010100101000010100000111011101001",
"10000000101100010000101100101101001011100000000100",
"10101001000000010100100001000100000100011110101001",
"00101001010101101001010100011010101101110000110101",
"11001010000100001100000010100101000001000111000010",
"00001000110000110101101000000100101001001000011101",
"10100101000101000000001110110010110101101010100001",
"00101000010000110101010000100010001001000100010101",
"10100001000110010001000010101001010101011111010010",
"00000100101000000110010100101001000001000000000010",
"11010000001001110111001001000011101001011011101000",
"00000110100010001000100000001000011101000000110011",
"10101000101000100010001111100010101001010000001000",
"10000010100101001010110000000100101010001011101000",
"00111100001000010000000110111000000001000000001011",
"10000001100111010111010001000110111010101101111000" };
mg = new int[30][50];
// 转换为整型数组(个人比较喜欢整型数组)
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 50; j++) {
mg[i][j] = s[i].charAt(j);
}
}
dfs(0, 0, "", 0);
System.out.println(res);
}
/** * * @param x x轴坐标
* @param y y轴坐标
* @param s 路径方向
* @param ans 总步数
*/
private static void dfs(int x, int y, String s, int ans) {
// 越界返回
if (x > 29 || x < 0 || y > 49 || y < 0)
return;
// 遇到障碍返回
if (mg[x][y] == 1)
return;
//出口
if(x == 29 && y == 49) {
if(max > ans) {
//记录最小值
max = ans;
s = res;
}
return ;
}
// 向右走
dfs(x, y + 1, s + "R", ans++);
ans--;// 回溯
// 向下走
dfs(x + 1, y, s + "D", ans++);
ans--;// 回溯
// 向上走
dfs(x - 1, y, s + "U", ans++);
ans--;// 回溯
// 向左走
dfs(x, y - 1, s + "L", ans++);
ans--;// 回溯
}
}


最后控制台爆栈了,请各位大神能帮我看看是哪里出的问题吗?
**
问题描述
问题描述
输入格式
输出格式
样例如下
评测用例规模与约定
这道题与第三题思路相似。采用枚举检查流程进行处理。遍历1至n的所有整数并执行检查操作,在符合条件的情况下将数值存储于数组中最后求取总和结果。我的代码:import java.util.Scanner;
特别数求和问题对应的Java程序
private static boolean check(int s) {
String S = s + "";
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == '2' || S.charAt(i) == '0' || S.charAt(i) == '1' || S.charAt(i) == '9')
return true;
}
return false;
}
}
这段代码应该不用继续优化了,我测试10000,很快就出答案了。
**
问题描述
输入格式
输出格式
样例输入
样例输出
评测用例规模与约定
这道题的复杂度骤然提升,在线编程竞赛中与一同参加比赛的朋友在这一道题上遇到了困难,并浪费了大量时间。我的解决思路是使用一个二维数组DD[T][N]来存储某一时刻的订单数据,在每个时间点上记录不同外卖商家的具体订单情况:其中DD[t][n]表示在t时刻第n家外卖店的订单数量。具体来说,在计算每个商家当前的时间段内的平均订单量时会根据其当前的实际订单情况进行调整:如果该外卖店在t时刻没有订单,则跳过该记录;否则,在计算其优先级时会根据当前订单数量进行调整——如果该商家在t时刻没有接单,则跳过;否则,在计算其优先级时会根据当前接单数量进行相应调整:若无接单则维持原有优先级水平;若有接单则根据实际接单数量进行动态修正:当某商家在其时间段内没有接单时则维持原有优先级水平;当某商家在其时间段内有接单记录时则对其优先级进行动态递增处理——具体来说就是将该商家在其时间段内的平均接单量乘以二后加到其当前累积计分值上;当遍历完所有时间段点后统计有多少家外卖店达到了优先级5的标准之后就可以得出最终结果了
import java.util.Scanner;
public class _07外卖店优先级 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int N = input.nextInt();
int M = input.nextInt();
int T = input.nextInt();
int[][] DD = new int[T + 1][N + 1];
for (int i = 0; i < M; i++) {
int t = input.nextInt();
int n = input.nextInt();
DD[t][n]++;
}
input.close();
// 商家优先级数组
int[] yx = new int[N + 2];
for (int i = 1; i < T + 1; i++) {
for (int j = 1; j < N + 1; j++) {
if (DD[i][j] == 0) {
if (yx[j] == 0)
continue;
if (yx[j] > 0)
yx[j]--;
} else if (DD[i][j] > 0) {
yx[j] = yx[j] + 2 * DD[i][j];
}
}
}
int sum = 0;
for (int i = 0; i < yx.length; i++) {
if (yx[i] >= 5)
sum++;
}
System.out.println(sum);
}
}

**
问题描述
输入格式
输入格式
当时解出了这道题,但未编写相应的测试用例。大概也只有及格线附近的成绩。总体思路尚不清晰。
**
问题描述
这道题比第八题简单,排序,然后大数相加,小数先减。
import java.util.Arrays;
import java.util.Scanner;
public class _09后缀表达式 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int add = input.nextInt();
int sub = input.nextInt();
int[] arr = new int[add + sub + 1];
for (int i = 0; i < arr.length; i++) {
arr[i] = input.nextInt();
}
input.close();
// Arrays的排序算法很好用,不需要自己再写一个排序算法。方法返回的是一个升序序列
Arrays.sort(arr);
for (int i = 0; i < arr.length / 2; i++) {
int t = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = t;
}
int sum = 0;
for (int i = 0; i < arr.length; i++) {
if (i <= add) {
sum += arr[i];
} else {
sum -= arr[i];
}
}
System.out.println(sum);
}
}

**
题目背景
问题描述
输入格式
输出格式
样例输入
样例输出
样例解释
这道题题目很长,并且已经是最后一道题了。然而完全没有时间去完成它,因此只能放弃作答。
为了便于总结。总体而言。相较于2018年的考题而言。我们大多数人持这种看法。希望本次考试能取得一个不错的成绩吧?但请注意这只是个人意见。谢谢各位的耐心阅读。
