博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第六届蓝桥杯java B组决赛真题详解
阅读量:3966 次
发布时间:2019-05-24

本文共 11071 字,大约阅读时间需要 36 分钟。

第六届蓝桥杯java B组决赛真题详解

1、分机号

X老板脾气古怪,他们公司的电话分机号都是3位数,老板规定,所有号码必须是降序排列,且不能有重复的数位。比如:

751,520,321 都满足要求,而,

766,918,201 就不符合要求。

现在请你计算一下,按照这样的规定,一共有多少个可用的3位分机号码?

请直接提交该数字,不要填写任何多余的内容。

思路:

这道题的解题方法很简单,根据题目的要求,枚举每一个三位数进行检查就可以解决问题

枚举+检查

public class question1 {
static int ans=0; public static void main(String args[]) {
int ans=0; //根据题目要求,三位不重复的数,且依次递减,因为范围很小,我们可以直接枚举在这个区间的每一个数,最小值是210,最大值应该为987 for(int i=210;i<=987;i++) {
int num=i; int a,b,c; a=num%10; //第三位数字 b=num/10%10; //第二位数字 c=num/100; //第一位数字 //判断当前分机号的三位数字依次递减且不存在重复数字 if(a

最终答案:120

2、五星填数

如【图1.png】的五星图案节点填上数字:1~12,除去7和11。

要求每条直线上数字和相等。

如图就是恰当的填法。

请你利用计算机搜索所有可能的填法有多少种。

注意:旋转或镜像后相同的算同一种填法。

请提交表示方案数目的整数,不要填写任何其它内容。

图1.jpg
图2.jpg

思路:解题思路在代码的注释里面

全排列+检查+回溯

/* 解题思路 这道题可以变成对1,2,3,4,5,6,8,9,10,12几个数字进行全排列 然后检查每种排列是否满足要求,满足要求就将填发增加1 因为旋转或镜像后相同的算作同一种方法,可以每种填发可以经过旋转可以有5种形式,经过镜像之后有5中形式 将最后算的的结果除以10就是最终的答案 */public class question2 {
static int count=0; public static void main(String args[]) {
int[] a= {
1,2,3,4,5,6,8,9,10,12}; f(a,0,a.length-1); System.out.println("ans="+count/10); //满足条件的全排列的数量除以10,就是本题的结果 } private static void f(int[] a, int start, int end) {
if(start==end) {
//全排列完成,检查排列的结果,如果满足要求就将解法加一 if(check(a)) count++; } //将当前位后面的每一位都和当前的这一位数字发生交换,完成全排列 for (int i = start; i <= end; i++) {
swap(a,i,start); //交换 f(a, start+1, end); swap(a,i,start); //回溯,将这次循环中的交换恢复,保证数组的内容不发生变化 } } //检查排列结果,即对每一条边上的值求和,判断各条边是否相等 private static boolean check(int[] a) {
int x=a[1]+a[4]+a[5]+a[6]; int y=a[1]+a[3]+a[7]+a[8]; int z=a[2]+a[4]+a[8]+a[9]; int h=a[0]+a[3]+a[5]+a[9]; int m=a[0]+a[2]+a[6]+a[7]; if(x==y&&x==z&&x==h&&x==m) return true; return false; } //交换数组中的两个指定下标的元素 private static void swap(int[] a, int i, int start) {
int b=a[i]; a[i]=a[start]; a[start]=b; }}

最终答案:12

3、显示二叉树(代码填空)

题目

标题:显示二叉树排序二叉树的特征是:某个节点的左子树的所有节点值都不大于本节点值。某个节点的右子树的所有节点值都不小于本节点值。为了能形象地观察二叉树的建立过程,小明写了一段程序来显示出二叉树的结构来。class BiTree{
private int v; private BiTree l; private BiTree r; public BiTree(int v){
this.v = v; } public void add(BiTree the){
if(the.v < v){
if(l==null) l = the; else l.add(the); } else{
if(r==null) r = the; else r.add(the); } } public int getHeight(){
int h = 2; int hl = l==null? 0 : l.getHeight(); int hr = r==null? 0 : r.getHeight(); return h + Math.max(hl,hr); } public int getWidth(){
int w = (""+v).length(); if(l!=null) w += l.getWidth(); if(r!=null) w += r.getWidth(); return w; } public void show(){
char[][] buf = new char[getHeight()][getWidth()]; printInBuf(buf, 0, 0); showBuf(buf); } private void showBuf(char[][] x){
for(int i=0; i
p2) buf[y+1][p3] = '\\'; if(l!=null) l.printInBuf(buf,x,y+2); if(r!=null) r.printInBuf(buf,p2+sv.length(),y+2); } private int getRootPos(int x){
return l==null? x : x + l.getWidth(); }}public class Main{
public static void main(String[] args) {
BiTree tree = new BiTree(500); tree.add(new BiTree(200)); tree.add(new BiTree(509)); tree.add(new BiTree(100)); tree.add(new BiTree(250)); tree.add(new BiTree(507)); tree.add(new BiTree(600)); tree.add(new BiTree(650)); tree.add(new BiTree(450)); tree.add(new BiTree(510)); tree.add(new BiTree(440)); tree.add(new BiTree(220)); tree.show(); }}对于上边的测试数据,应该显示出: | /--------------500---\ | |/--200---\ /--509---\| | | |100 /--250---\ 507 /--600\ | | | | 220 /--450 510 650 | 440(如有对齐问题,请参考【图1.png】)请分析程序逻辑,填写划线部分缺失的代码。注意,只填写缺少的部分,不要填写已有的代码或符号,也不要加任何说明文字。

思路

对于这种代码填空的题目,完全没有必要完全看懂代码,既然只让写一行代码,那就肯定是关键的语句,可以使用Debug的方式来解决这种题目,先把要填写代码的行注释掉,然后运行这段代码,观察实际输出的结果和题目又什么差别,然后再去填写代码,基本上要填写的哪一行里就是在程序中定义过却从未使用的变量,或者是比较关键的变量,掌握这种思路求解这类问题就会很简单。

最终答案

buf[y+1][i+p2]=sv.toCharArray()[i];

4、穿越雷区

X星的坦克战车很奇怪,它必须交替地穿越正能量辐射区和负能量辐射区才能保持正常运转,否则将报废。

某坦克需要从A区到B区去(A,B区本身是安全区,没有正能量或负能量特征),怎样走才能路径最短?

已知的地图是一个方阵,上面用字母标出了A,B区,其它区都标了正号或负号分别表示正负能量辐射区。

例如:

A + - + -- + - - +- + + + -+ - + - +B + - + -

坦克车只能水平或垂直方向上移动到相邻的区。

数据格式要求:

输入第一行是一个整数n,表示方阵的大小, 4<=n<100

接下来是n行,每行有n个数据,可能是A,B,+,-中的某一个,中间用空格分开。
A,B都只出现一次。

要求输出一个整数,表示坦克从A区到B区的最少移动步数。

如果没有方案,则输出-1

例如:

用户输入:

5A + - + -- + - - +- + + + -+ - + - +B + - + -

则程序应该输出:

10

资源约定:

峰值内存消耗(含虚拟机) < 512M
CPU消耗 < 2000ms

思路

基本思路:

求解在图中的最短路径问题,用到的算法大多数都是BFS(广度优先搜索),因为是广度优先搜索,所以找到的结果就是最短路径。

明确了要用到的算法,接下来问题就会变得简单很多,无非就是节点能不能走得通的判断
从起始位置进行BFS,搜索四周的几个节点,如果节点在地图范围内且可以行走(可以行走的条件是下一个节点的值和本节点不同,即题目所说的坦克必须交替穿越正能量辐射区和负能量辐射区),则在下一步走到四周的某一个可以走得通的节点,并将路径数目增加1,一直到找到B节点退出BFS,路径距离即为所求。

代码思路:

首先定义一个节点的类Node,用来存储每一个可以行走的节点,接着声明一个队列Queue,用来存储可以走的通的节点,不停执行入队和出队操作,直到当前队列为空(走不通)时结束,返回-1,或者走到B节点,返回路径长度。

因为行走过程中可能会重复走过一个节点,为了优化代码,降低时间复杂度,可以设置一个二维的布尔数组,用来标记一个节点是否被走过,若走过则不在对该节点执行入队操作

知识要点:

队列,BFS,字符串处理,节点判断,代码优化

代码
import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;public class question4 {
//字符数组,用来存储地图 static char[][] array; static int n; public static void main(String args[]) {
Scanner in=new Scanner(System.in); //对用户输入进行处理,此处不做解析 n=in.nextInt(); array=new char[n][n]; String s=""; in.nextLine(); for (int i = 0; i < n; i++) {
s=in.nextLine().replaceAll(" ", ""); for (int j = 0; j < n; j++) {
array[i][j]= s.toCharArray()[j]; } } int x=0,y=0; //查找A节点,即起始位置,从该处开始执行BFS for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if(array[i][j]=='A') {
x=i;y=j; } } if(x!=0) break; } //实例化一个节点,从此处开始查找 Node node=new Node(x, y, 'A', 0); System.out.println(f(node)); } private static int f(Node node) {
Queue
q=new LinkedList
(); //声明一个队列,存储当前可以走的通的节点 q.add(node); //起始节点入队 boolean[][] flag=new boolean[n][n]; //标志数组,标记每一个节点是否被走过 int[] x= {
1,0,-1,0}; int[] y= {
0,1,0,-1}; while (!q.isEmpty()) {
//如果队列非空 Node now=q.peek(); //取出队头节点 flag[now.x][now.y]=true; //标记该节点已经被访问过了 q.remove(); //移除已经访问过的节点 for(int i=0;i<4;i++) {
//遍历当前节点的四周节点 //遍历当前节点的四周的每个节点 //得到当前节点的下一个节点的位置和属性 int next_x=now.x+x[i]; int next_y=now.y+y[i]; if(next_x<0||next_x>=n||next_y<0||next_y>=n) //如果这个节点不在地图范围内,直接退出,寻找下一个相邻节点 continue; char next_value=array[next_x][next_y]; int next_step=now.step+1; if(next_value=='B') //如果这个节点是B,返回路径长度 return next_step; if(now.value!=next_value&&flag[next_x][next_y]==false) //当前节点和下一个节点不同(交替穿越正负能量区),且下一个节点没有没有访问过,将其加入队尾 {
Node next=new Node(next_x, next_y, next_value, next_step); q.add(next); } } } //如果走不通,返回-1 return -1; } }//节点类,标记图中的每一个节点class Node{
int x; //节点的x坐标 int y; //节点的y坐标 char value; //节点的值 int step; //到达该节点的最短路径长度 public Node(int x, int y, char value, int step) {
super(); this.x = x; this.y = y; this.value = value; this.step = step; }}

5、表格计算

某次无聊中, atm 发现了一个很老的程序。这个程序的功能类似于 Excel ,它对一个表格进行操作。

不妨设表格有 n 行,每行有 m 个格子。
每个格子的内容可以是一个正整数,也可以是一个公式。
公式包括三种:

  1. SUM(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的和。
  2. AVG(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的平均数。
  3. STD(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的标准差。

标准差即为方差的平方根。

方差就是:每个数据与平均值的差的平方的平均值,用来衡量单个数据离开平均数的程度。

公式都不会出现嵌套。

如果这个格子内是一个数,则这个格子的值等于这个数,否则这个格子的值等于格子公式求值结果。

输入这个表格后,程序会输出每个格子的值。atm 觉得这个程序很好玩,他也想实现一下这个程序。

「输入格式」

第一行两个数 n, m 。
接下来 n 行输入一个表格。每行 m 个由空格隔开的字符串,分别表示对应格子的内容。
输入保证不会出现循环依赖的情况,即不会出现两个格子 a 和 b 使得 a 的值依赖 b 的值且 b 的值依赖 a 的值。

「输出格式」

输出一个表格,共 n 行,每行 m 个保留两位小数的实数。
数据保证不会有格子的值超过 1e6 。

「样例输入」

3 2
1 SUM(2,1:3,1)
2 AVG(1,1:1,2)
SUM(1,1:2,1) STD(1,1:2,2)

「样例输出」

1.00 5.00
2.00 3.00
3.00 1.48

「数据范围」

对于 30% 的数据,满足: n, m <= 5
对于 100% 的数据,满足: n, m <= 50

资源约定:

峰值内存消耗(含虚拟机) < 512M
CPU消耗 < 2000ms

思路:

递归求解每一个公式的结果。

声明一个double的二维数组存放格子的数字,声明一个String二维数组存放用书输入每一个格子的内容,声明一个boolean二维数标记每一个格子是公式还是数值。

对于是公式的格子,根据公式类型调用对应的函数求解,因为平均值和方差都需要用到求和公式,所以只需在求和函数sum()里面进行递归操作,详细操作参考程序代码,本题不做详细解释。

本题需要定义5个方法

static void f(int i, int j)							//求解一个公式的格子,将结果赋给存放数值的数组,并将格子标记为是一个数字 double sum(int x1,int y1,int x2,int y2)				//求解(x1,y1,x2,y2)范围内的和 static double avg(int x1,int y1,int x2,int y2) 		//求解(x1,y1,x2,y2)范围内的平均数 double std(int x1,int y1,int x2,int y2)				//求解(x1,y1,x2,y2)范围内的标准差 boolean check(String s)								//检查一个字符串是不是公式,如果是返回true,不是返回false

源码

import java.io.StreamCorruptedException;import java.util.Scanner;import java.util.regex.Matcher;import java.util.regex.Pattern;public class question5 {
static int n,m; static String[][] str; static double[][] array; static boolean[][] flag; public static void main(String args[]) {
//首先解决输入问题 Scanner in=new Scanner(System.in); n=in.nextInt(); m=in.nextInt(); str=new String[n][m]; array=new double[n][m]; flag=new boolean[n][m]; in.nextLine(); //将剩余的空行读出,开始接收数据 for (int i = 0; i < n; i++) {
String[] s=in.nextLine().split(" "); for (int j = 0; j < m; j++) {
str[i][j]=s[j]; } } //输入问题已解决,开始进行数据的转换,首先进行初始数据的转换,就是用户刚开始输入的内容 for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if(check(str[i][j])) continue; flag[i][j]=true; array[i][j]=Double.parseDouble(str[i][j]); } } for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if(!flag[i][j]) {
//如果当前的这个格子不是数字,进行转换 f(i,j); } } } //数据转换已完成,开始向外输出数据 for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.printf("%.2f\t",array[i][j]); } System.out.println(); } } private static void f(int i, int j) {
double ans=0; String[] value=((String) str[i][j].subSequence(4, str[i][j].length()-1)).split(":"); //将里面的四个值提取出来 int x1=Integer.parseInt(value[0].split(",")[0]); int y1=Integer.parseInt(value[0].split(",")[1]); int x2=Integer.parseInt(value[1].split(",")[0]); int y2=Integer.parseInt(value[1].split(",")[1]); if(((String)str[i][j].subSequence(0, 3)).equals("SUM")) ans=sum(x1,y1,x2,y2); if(((String)str[i][j].subSequence(0, 3)).equals("AVG")) ans=avg(x1,y1,x2,y2); if(((String)str[i][j].subSequence(0, 3)).equals("STD")) ans=std(x1,y1,x2,y2); array[i][j]=ans; flag[i][j]=true; } //这三个函数是三个公式 static double sum(int x1,int y1,int x2,int y2) {
double sum=0; for (int i = x1-1; i < x2; i++) {
for (int j = y1-1; j < y2; j++) {
if(!flag[i][j]) f(i, j); sum+=array[i][j]; } } return sum; } static double avg(int x1,int y1,int x2,int y2) {
double sum=0; sum=sum(x1, y1, x2, y2); int count=(x2-x1+1)*(y2-y1+1); sum=sum/count; return sum; } static double std(int x1,int y1,int x2,int y2) {
double avg=avg(x1, y1, x2, y2); double sum=0; int count=(x2-x1+1)*(y2-y1+1); for (int i = x1-1; i < x2; i++) {
for (int j = y1-1; j < y2; j++) {
sum+=Math.pow((array[i][j]-avg), 2); } } sum=sum/count; //方差 sum=Math.sqrt(sum); //标准差 return sum; } //检查一个字符串是不是公式,如果是返回true,不是返回false static boolean check(String s) {
char c=s.toCharArray()[0]; if(c>60) return true; else return false; } }/*样例输入3 21 SUM(2,1:3,1)2 AVG(1,1:1,2)SUM(1,1:2,1) STD(1,1:2,2)样例输出1.00 5.002.00 3.003.00 1.48 */

转载地址:http://qwezi.baihongyu.com/

你可能感兴趣的文章
举例说明常用字符串处理函数
查看>>
软件生存期模型
查看>>
制定计划(问题的定义,可行性研究)
查看>>
需求分析
查看>>
软件设计
查看>>
程序编码
查看>>
软件测试
查看>>
软件维护
查看>>
软件项目管理
查看>>
面向过程的分析方法
查看>>
软件设计基础
查看>>
UML的基本结构
查看>>
UML中几种类间关系:继承、实现、依赖、关联、聚合、组合的联系与区别
查看>>
用例图(UseCase Diagram)—UML图(一)
查看>>
类图(Class diagram)—UML图(二)
查看>>
活动图(Activity Diagram)—UML图(四)
查看>>
C#方法重载(overload)方法重写(override)隐藏(new)
查看>>
CSS+DIV练手-公司
查看>>
CSS+DIV练手—鲜花展
查看>>
深入浅出JavaScript(1)—ECMAScript
查看>>