上一篇文章:2022年第十三届蓝桥杯比赛Java B组 【全部真题答案解析-第一部分】_尘封的CPU的博客-CSDN博客最近回顾了Java B组的试题,深有感触:脑子长时间不用会锈住,很可怕。兄弟们,都给我从被窝里爬起来,赶紧开始卷!!!https://blog.csdn.net/kndjg/article/details/127696158?spm=1001.2014.3001.5502
继上一篇题目解析文章,本文分析G~J题,全部是编程题,欢迎兄弟们一起讨论;废话不多说,直接整活儿!
2022年第十三届蓝桥杯Java B组(第二部分 G~J题)
试题 G: 数组切分
时间限制: 1.0s内存限制: 512.0MB本题总分:20 分【问题描述】已知一个长度为 N 的数组: A1, A2, A3, ... A N 恰好是 1 ∼ N 的一个排列。现在要求你将 A 数组切分成若干个 (最少一个,最多 N 个) 连续的子数组,并且每个子数组中包含的整数恰好可以组成一段连续的自然数。例如对于 A = {1, 3, 2, 4}, 一共有 5 种切分方法:{1}{3}{2}{4}:每个单独的数显然是 (长度为 1 的) 一段连续的自然数。{1}{3, 2}{4}:{3, 2} 包含 2 到 3,是 一段连续的自然数,另外 {1} 和 {4} 显然也是。{1}{3, 2, 4}:{3, 2, 4} 包含 2 到 4,是 一段连续的自然数,另外 {1} 显然也是。{1, 3, 2}{4}:{1, 3, 2} 包含 1 到 3,是 一段连续的自然数,另外 {4} 显然也是。{1, 3, 2, 4}:只有一个子数组,包含 1 到 4,是 一段连续的自然数。【输入格式】第一行包含一个整数 N。第二行包含 N 个整数,代表 A 数组。【输出格式】输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取模后的值【样例输入】41 3 2 4【样例输出】5【评测用例规模与约定】对于 30% 评测用例,1 ≤ N ≤ 20.对于 100% 评测用例,1 ≤ N ≤ 10000.
思路与题解
// 代码
试题 H: 回忆迷宫
时间限制: 1.0s内存限制: 512.0MB本题总分:20 分【问题描述】爱丽丝刚从一处地下迷宫中探险归来,你能根据她对于自己行动路径的回忆,帮她画出迷宫地图吗?迷宫地图是基于二维网格的。爱丽丝会告诉你一系列她在迷宫中的移动步骤,每个移动步骤可能是上下左右四个方向中的一种,表示爱丽丝往这个方向走了一格。你需要根据这些移动步骤给出一个迷宫地图,并满足以下条件:1、爱丽丝能在迷宫内的某个空地开始,顺利的走完她回忆的所有移动步骤。2、迷宫内不存在爱丽丝没有走过的空地。3、迷宫是封闭的,即可通过墙分隔迷宫内与迷宫外。任意方向的无穷远处视为迷宫外,所有不与迷宫外联通的空地都视为是迷宫内。(迷宫地图为四联通,即只有上下左右视为联通)4、在满足前面三点的前提下,迷宫的墙的数量要尽可能少。【输入格式】第一行一个正整数 N,表示爱丽丝回忆的步骤数量。接下来一行 N 个英文字符,仅包含 UDLR 四种字符,分别表示上(Up)、下(Down)、左(Left)、右(Right)。【输出格式】请通过字符画的形式输出迷宫地图。迷宫地图可能包含许多行,用字符 ‘*’表示墙,用 ‘ ’(空格)表示非墙。你的输出需要保证以下条件:1、至少有一行第一个字符为 ‘*’。2、第一行至少有一个字符为 ‘*’。3、每一行的最后一个字符为 ‘*’。4、最后一行至少有一个字符为 ‘*’。【样例输入】17UUUULLLLDDDDRRRRU【样例输出】****** ** *** ** *** ** *** ** ******【样例说明】爱丽丝可以把第六行第六个字符作为起点。外墙墙墙墙墙外墙内内内内内墙墙内墙墙墙内墙墙内墙墙墙内墙墙内墙墙墙内墙墙内内内内内墙外墙墙墙墙墙外【评测用例规模与约定】对于所有数据,0 < N ≤ 100.
思路与题解
本题只是涉及二维数组的边界问题。
首先声明一个二维数组,0表示墙 1表示非墙,爱丽丝默认在数组的中间位置,定义上下左右四个边界在原点四周,表示迷宫(数组)的打印范围;
遍历字符串每一个字符,每读取一个字符改变一次爱丽丝的位置(x,y),并将当前位置的数组元素值置1,当坐标(x,y)与边界重合时,相应的边界向外围方向扩张1格;
最终根据四个边界值打印迷宫图形,0表示*,1表示空格。
public static void Java_B_H() {
Scanner scanner = new Scanner(System.in);
int len = scanner.nextInt();
String route = scanner.next();
int arr[][] = new int[200][200];
int x = 99, y = 99;
arr[x][y] = 1;
int left = x - 1, right = x + 1, up = y - 1, down = y + 1;
for (int i = 0; i < len; i++) {
char ch = route.charAt(i);
switch (ch) {
case 'U':
y -= 1;
if (y == up)
up--;
break;
case 'D':
y += 1;
if (y == down)
down++;
break;
case 'L':
x -= 1;
if (x == left)
left--;
break;
case 'R':
x += 1;
if (x == right)
right++;
break;
default:
System.out.println("输入有误,程序中断!");
return;
}
arr[x][y] = 1;
}
arr[left][up] = 1;
arr[left][down] = 1;
arr[right][up] = 1;
arr[right][down] = 1;
for (int j = up; j <= down; j++) {
for (int i = left; i <= right; i++) {
if (arr[i][j] == 1)
System.out.print(" ");
else
System.out.print("*");
}
System.out.println();
}
}
试题 I: 红绿灯
时间限制: 1.0s内存限制: 512.0MB本题总分:25 分【问题描述】爱丽丝要开车去上班,上班的路上有许多红绿灯,这让爱丽丝很难过。为 了上班不迟到,她给自己的车安装了氮气喷射装置。现在她想知道自己上班最短需要多少时间。爱丽丝的车最高速度是 1/V 米每秒,并且经过改装后,可以瞬间加速到小于等于最高速的任意速度,也可以瞬间停止。爱丽丝家离公司有 N 米远,路上有 M 个红绿灯,第 i 个红绿灯位于离爱丽丝家 A i 米远的位置,绿灯持续 B i 秒,红灯持续 C i 秒。在初始时(爱丽丝开始计时的瞬间),所有红绿灯都恰好从红灯变为绿灯。如果爱丽丝在绿灯变红的瞬间到达红绿灯,她会停下车等红灯,因为她是遵纪守法的好市民。氮气喷射装置可以让爱丽丝的车瞬间加速到超光速(且不受相对论效应的影响!),达到瞬移的效果,但是爱丽丝是遵纪守法的好市民,在每个红绿灯前她都会停下氮气喷射,即使是绿灯,因为红绿灯处有斑马线,而使用氮气喷射装置通过斑马线是违法的。此外,氮气喷射装置不能连续启动,需要一定时间的冷却,表现为通过 K 个红绿灯后才能再次使用。(也就是说,如果 K = 1,就能一直使用啦!)初始时,氮气喷射装置处于可用状态。【输入格式】第一行四个正整数 N、 M、 K、 V,含义如题面所述。接下来 M 行,每行三个正整数 A i、 B i、 C i,含义如题面所述。【输出格式】输出一个正整数 T,表示爱丽丝到达公司最短需要多少秒。【样例输入】90 2 2 230 20 2060 20 20【样例输出】80【样例说明】爱丽丝在最开始直接使用氮气喷射装置瞬间到达第一个红绿灯,然后绿灯通过,以最高速行进 60 秒后到达第二个红绿灯,此时绿灯刚好变红,于是她等待 20 秒再次变为绿灯后通过该红绿灯,此时氮气喷射装置冷却完毕,爱丽丝再次使用瞬间到达公司,总共用时 80 秒。【评测用例规模与约定】对于 30% 的数据, N ≤ 100; M ≤ 10; M < K; V = 1.对于 60% 的数据, N ≤ 1000; M ≤ 100; K ≤ 50; B i, C i ≤ 100; V ≤ 10.对于 100% 的数据,0 < N ≤ 108; M ≤ 1000; K ≤ 1000; 0 < B i, C i ≤ 106 ; 0 <V ≤ 106 ; 0 < A i < N; 对任意 i < j, 有 A i < A j.
思路与题解
根据m个红绿灯把路程分为m+1段 一段路: _________!(感叹号为红绿灯)
经过每一段路需要的时间:赶路时间+等红绿灯时间
用氮气则赶路时间为0,绿灯则等红绿灯时间为0 深度搜索遍历
static int n;// 距离
static int m;// 红灯数
static int k;// 氮气就绪次数
static int v;// 速度
static int[] av = null;// 经过该红绿灯所需时间a*v
static int[] b = null;// 绿灯持续时间
static int[] c = null;// 红灯持续时间
static int minTime = 999999999;
public static void Java_B_I() {
// 入口方法
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
k = scan.nextInt();
v = scan.nextInt();
// System.out.println(""+n+m+k+v);
av = new int[m + 1];// 共m+1段路
b = new int[m + 1];
c = new int[m + 1];
int s = 0;
for (int i = 0; i < m; i++) {
int a1 = scan.nextInt();
int a2 = scan.nextInt();
int a3 = scan.nextInt();
av[i] = (a1 - s) * v;
s += a1;
b[i] = a2;
c[i] = a3;
}
if (s < n) {
av[m] = (n - s) * v;
b[m] = -1;
c[m] = -1;
}
run(0, 0, 0);
System.out.println(minTime);
}
public static int abc(int p, int newTime) {
int wait = 0;
wait = (newTime) % (b[p] + c[p]);
if (wait < b[p]) {// 绿灯,冲
return 0;
} else {
return b[p] + c[p] - wait;// 返回等红灯时间
}
}
public static int run(int p, int kk, int newTime) {
if (p == m) {// 最后一段路没红绿灯
if (kk > 0) {// 没有氮气自己爬
newTime += av[m];
}
if (minTime > newTime) {
minTime = newTime;// 提交成功结果
}
return 1;
} else {// 不是最后一段
if (newTime >= minTime) {
return 0;// 剪枝
}
if (kk == 0) {// 有氮气就冲
kk = k - 1;// 缓冲氮气
newTime += abc(p, newTime);// 等红灯
run(p + 1, kk, newTime);
} else {// 不用氮气可以爬捏
if (kk > 0) {
kk--;
}
newTime += av[p];// 爬过中间路段
newTime += abc(p, newTime);// 等红灯
run(p + 1, kk, newTime);
}
}
return 0;
}