2020蓝桥杯JavaB组部分题解

试题 A: 门牌制作
本题总分:5 分
【问题描述】
小蓝要为一条街的住户制作门牌号。
这条街一共有 2020 位住户,门牌号从 1 到 2020 编号。
小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字
符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、0、1、7,即需要 1 个
字符 0,2 个字符 1,1 个字符 7。
请问要制作所有的 1 到 2020 号门牌,总共需要多少个字符 2?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

对2到2020循环取模,计2的个数即可
答案是624

public calss Main{

 public static void main(String[] args){
        int ans = 0;
		int n = 0;
		for(int i = 2 ; i <= 2020 ; i ++) {
			n = i;
			while(n>10){
				if(n%10 == 2) {
					ans ++;
				}
				n /= 10;
				}
		if(n == 2) {
			ans ++;
		}
	}
System.out.println(ans);
  }

}


试题 C: 蛇形填数
本题总分:10 分
【问题描述】
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
1 2 6 7 15 …
3 5 8 14 …
4 9 13 …
10 12 …
11 …

(1)
容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列
的数是多少?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

纯数学题目 仔细观察发现第n行第n列为(n-1)^2 + n*n

所以第20行20列的数字是19X19+20X20=761

代码解决:把矩阵斜着看就是一个金字塔:

1

3 2

4 5 6

10 9 8 7

………………………………………………………………………………………………

public class Main {

	public static void main(String[] args) {
		int[][] arr = new int[100][100];
		int count = 1 ;
		for(int i = 0 ; i < 100 ; i ++) {
			for(int j = 0 ; j < i + 1 ; j ++) {
				arr[i-j][j] = count ++;
			}
		}
		System.out.println(arr[19][19]);
	}
	

}

试题 F: 成绩分析
时间限制: 1.0s 内存限制: 512.0MB 本题总分:15 分
【问题描述】
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是
一个 0 到 100 的整数。
请计算这次考试的最高分、最低分和平均分。
【输入格式】
输入的第一行包含一个整数 n,表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
【输出格式】
输出三行。
第一行包含一个整数,表示最高分。
第二行包含一个整数,表示最低分。
第三行包含一个实数,四舍五入保留正好两位小数,表示平均分。
【样例输入】
7
80
92
56
74
88
99
10

【样例输出】
99
10
71.29
【评测用例规模与约定】
对于 50% 的评测用例,1 ≤ n ≤ 100。
对于所有评测用例,1 ≤ n ≤ 10000。

直接取最大值最小值和平均值保留两位小数输出就行:

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int n=scanner.nextInt();
		int max=0;
		min=101;
		double sum=0;
		for(int i=0;i<n;i++){
			int t=scanner.nextInt();
			min=Math.min(min, t);
			max=Math.max(max, t);
			sum+=t;
		}
		System.out.println(max+"\n"+min+"\n"+String.format("%.2f", sum/n));
	}
}

试题 G: 单词分析
时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分
【问题描述】
小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组
成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不
住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得
最多来分辨单词。
现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这
个字母出现的次数。
【输入格式】
输入一行包含一个单词,单词只由小写英文字母组成。
【输出格式】
输出两行,第一行包含一个英文字母,表示单词中出现得最多的字母是哪
个。如果有多个字母出现的次数相等,输出字典序最小的那个。
第二行包含一个整数,表示出现得最多的那个字母在单词中出现的次数。
【样例输入】
lanqiao
【样例输出】
a
2
【样例输入】
longlonglongistoolong
【样例输出】
o
6
【评测用例规模与约定】
对于所有的评测用例,输入的单词长度不超过 1000

用一个长度26的数组来存储每个字母出现的次数即可:

import java.util.Scanner;

public class Test {
public static void main(String[] args) {
	Scanner sca = new Scanner(System.in);
	String str = sca.nextLine();
	int[] arr = new int[26];
	for(int i = 0 ; i < str.length() ; i ++) {
		arr[str.charAt(i)-97] ++;
	}
	int max = 0;
	int local = 0;
	for(int i = 0 ; i < 26 ; i++) {
		if(arr[i]>max) {
			max = arr[i];
			local = i;
		}
	}
	System.out.println((char)(local+97));
	System.out.println(max);
}
}

试题 H: 数字三角形
时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分
【问题描述】

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。
对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最
大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右
边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
【输入格式】
输入的第一行包含一个整数 N (1 < N ≤ 100),表示三角形的行数。下面的
N 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。
【输出格式】
输出一个整数,表示答案。
【样例输入】
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
【样例输出】
27

如果采用传统的递归回溯,每一个数字都是加和不加两种状态,时间复杂度将会是O(2^n*n)

因此要采用动态规划的方式,取最大收益,对于i行j列的数据来说,j=0时没得选,只有一个方向那就是i-1行j-1列的数字,j=i时同样没得选,只能是来自i-1行j列,因此j=0和j=i时的路径和是固定的,本题样例中的数据整理如下:

7

10 15

18 1 15

20 7 4 19

24 5 2 6 29

最开始时可直接如此赋值

在来自两条路径中选择权值较大的一条
组队蓝桥杯java_用例
但是还没有结束,因为题目要求:向左下走的次数与向右下走的次数相差不能超过 1。因此有些路径的和最大,但是却不能选,例如本题中的样例:dp之后如下:

7

10 15

18 16 15

20 25 20 19

24 30 27 26 29

但是由于30这条路径是:7-15-16-25-30 左右步数差为2,不能选择,因此定义一个相同大小的二维数组path,来记录左右步数,j=0时一定是向左,j=i时一定向右:令向左为正,向右为负
组队蓝桥杯java_System_02
dp的时候path的值随着dp的路径来确定:
组队蓝桥杯java_System_03
最后需要判断如果path[n-1][i]的绝对值大于1就不能选

因此可得题解:

public class Main {
static int[][] dp ;
static int[][] path ; 
static int[][] arr ;
static int max = 0 ;
public static void main(String[] args) {
  Scanner sca = new Scanner(System.in);	
  int n = sca.nextInt();
  arr = new int[n][n];
  dp = new int[n][n];
  path = new int[n][n];
  
  for(int i = 0 ; i < n ; i ++) {
	  for(int j = 0 ; j <= i ; j ++) {
		  arr[i][j] = sca.nextInt();
		  if(i == 0)
			  dp[0][0] = arr[0][0];
	  }
	  if(i>=1) {
		  dp[i][0] = dp[i-1][0] + arr[i][0];
		  dp[i][i] = dp[i-1][i-1] + arr[i][i];
		  path[i][0] = i;
		  path[i][i] = -i;
	  }
  }
  for(int i = 2 ; i < n ; i ++) {
	  for(int j = 1; j <= i ; j ++) {
		  dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-1]) + arr[i][j];
		  if(dp[i][j] == dp[i-1][j] ) {
			  path[i][j] = path[i-1][j] + 1;
		  }else path[i][j] = path[i-1][j-1] - 1;
	  }
  }
  
   for(int i = 0 ; i < n ; i ++) {
	   
	       	   if(Math.abs(path[n-1][i])>1) {
    		   dp[n-1][i] = 0;
    	   }
    	   if(dp[n-1][i] > max) {
   		   max = dp[n-1][i];
    	   }
       }
       System.out.println(max);
	}

}

最后附上某位仁兄提供的数据:

25
14
9 28
19 9 24
25 9 18 40
28 13 38 28 44
19 31 41 18 2 23
5 12 43 32 18 24 32
17 17 27 32 41 47 41 46
3 33 31 43 48 20 21 4 31
35 39 44 34 24 1 40 12 36 46
29 29 46 39 34 20 46 19 32 46 17
26 32 6 15 29 15 20 10 41 16 48 16
0 11 11 35 25 42 16 31 11 21 32 23 12
7 2 14 49 10 31 8 38 4 16 35 20 30 9
33 24 41 29 35 4 2 45 12 32 6 36 36 23 40
10 47 20 47 40 9 37 41 32 48 22 49 14 10 11 46
25 10 39 15 13 25 4 1 1 30 6 11 9 44 32 33 11
22 0 5 14 46 32 20 17 29 15 28 31 26 21 45 7 8 42
13 10 33 37 1 25 30 29 30 45 16 31 7 20 23 11 31 1 18
28 18 45 41 13 48 40 13 1 30 41 12 3 2 48 27 47 22 19 15
9 18 17 10 35 22 31 12 14 36 16 6 40 10 38 25 7 7 3 34 13
23 36 48 36 7 18 6 19 41 12 5 16 0 19 31 16 3 27 27 12 16 20
2 47 11 20 37 19 39 35 37 28 31 12 27 43 40 46 37 26 34 9 8 27 35
31 36 6 9 26 27 48 36 47 46 46 24 14 17 11 30 30 17 29 25 0 45 26 41
18 46 42 34 39 47 41 30 3 6 9 19 41 1 25 24 33 23 16 3 49 33 1 43 43

答案是783