2020年蓝桥杯省模拟赛

2020年4月18日蓝桥杯省模拟赛
第一题:
问题描述:
  由1对括号,可以组成一种合法括号序列:()。
  由2对括号,可以组成两种合法括号序列:()()、(())。
  由4对括号组成的合法括号序列一共有多少种?
答案提交
  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
  答案:14
法一: 由于给的数字并不是特别的大,直接在纸上算也可以
法二: 参考LeetCode22题,括号生成。
算法参考图片:
2020年蓝桥杯省模拟赛_第1张图片

package zzctst;

import java.util.ArrayList;
import java.util.Scanner;

public class test01 {
	static int sum = 0;
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		ArrayList<String> list = new ArrayList<String>();
		int n = in.nextInt();
		
		dfs("", n, n, list);
		
		System.out.println(sum);
	}
	
	static void dfs(String str, int left, int right, ArrayList<String> list){
		//出口
		if(left == 0 && right == 0){
			sum++;
			list.add(str);
			return;
		}
		//特别的,若左括号的剩余量大于右括号
		if(left > right) return;
		//拼接左括号
		if(left > 0){
			dfs(str + "(", left - 1, right, list);
		}
		//拼接右括号
		if(right > 0){
			dfs(str + ")", left, right - 1, list);
		}
	}
}

第二题:
  在计算机存储中,12.5MB是多少字节?
答案提交
  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
  答案:13107200
  
第三题:
将LANQIAO中的字母重新排列,可以得到不同的单词,如LANQIAO、AAILNOQ等,注意这7个字母都要被用上,单词不一定有具体的英文意义。
  请问,总共能排列如多少个不同的单词。
答案提交
  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
  答案:2520
  注意:中间有两个A
  法一:7!/2 = 2520
  法二:代码如下(注意去重)LeetCode46题

package zzctst;

import java.util.Arrays;
import java.util.HashSet;

public class test03 {
	static HashSet<String> set = new HashSet<String>();
	
	public static void main(String[] args) {
		String str = "LANQIAO";
		char[] ch = str.toCharArray();
		dfs(ch, 0);
		System.out.println(set.size());
	}
	
	static void dfs(char [] arra, int begin){
		if(begin == arra.length){
			set.add(new String(arra));
			return;
		}
		for(int i = begin; i < arra.length; i++){
			//每个数字当一次头
			char temp = arra[begin];
			arra[begin] = arra[i];
			arra[i] = temp;
			
			dfs(arra, begin + 1);
			
			//回溯
			temp = arra[begin];
			arra[begin] = arra[i];
			arra[i] = temp;
		}
	}
}

第四题:(概念)
一个包含有2019个结点的无向连通图,最少包含多少条边?
答案提交
  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
  答案:2018
  
第五题
 给定三个整数 a, b, c,如果一个整数既不是 a 的整数倍也不是 b 的整数倍还不是 c 的整数倍,则这个数称为反倍数。
  请问在 1 至 n 中有多少个反倍数。
输入格式
  输入的第一行包含一个整数 n。
  第二行包含三个整数 a, b, c,相邻两个数之间用一个空格分隔。
输出格式
  输出一行包含一个整数,表示答案。
样例输入
30
2 3 6
样例输出
10
样例说明
以下这些数满足要求:1, 5, 7, 11, 13, 17, 19, 23, 25, 29。

package zzctst;

import java.util.Scanner;

public class test05 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int a = in.nextInt();
		int b = in.nextInt();
		int c = in.nextInt();
		//遍历1到n
		int sum = 0;
		for(int i = 1; i <= n; i++){
			if(i % a != 0 && i % b != 0 && i % c != 0){
				sum++;
			}
		}
		System.out.println(sum);
	}
}

第六题:
给定一个单词,请使用凯撒密码将这个单词加密。
  凯撒密码是一种替换加密的技术,单词中的所有字母都在字母表上向后偏移3位后被替换成密文。即a变为d,b变为e,…,w变为z,x变为a,y变为b,z变为c。
  例如,lanqiao会变成odqtldr。
输入格式
  输入一行,包含一个单词,单词中只包含小写英文字母。
输出格式
  输出一行,表示加密后的密文。
样例输入
lanqiao
样例输出
Odqtldr

package zzctst;

import java.util.Scanner;

public class test06 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		//System.out.println((char)((int)'a'+3));
		String str = in.next();
		char[] ch = str.toCharArray();
		for(int i = 0; i < str.length(); i++){
			if(ch[i] == 'x'){
				ch[i] = 'a';
			}else if(ch[i] == 'y'){
				ch[i] = 'b';
			}else if(ch[i] == 'z'){
				ch[i] = 'c';
			}else{
				ch[i] = (char)((int)ch[i] + 3);
			}
		}
		System.out.println(new String(ch));
	}
}

第七题
对于一个 n 行 m 列的表格,我们可以使用螺旋的方式给表格依次填上正整数,我们称填好的表格为一个螺旋矩阵。
  例如,一个 4 行 5 列的螺旋矩阵如下:
  1 2 3 4 5
  14 15 16 17 6
  13 20 19 18 7
  12 11 10 9 8
输入格式
  输入的第一行包含两个整数 n, m,分别表示螺旋矩阵的行数和列数。
  第二行包含两个整数 r, c,表示要求的行号和列号。
输出格式
  输出一个整数,表示螺旋矩阵中第 r 行第 c 列的元素的值。
样例输入
4 5
2 2
样例输出
15
我的理解:LeetCode54题

  • 旋转列入整数,我们可以理解为当前数组的行数和列数在不断的减小,也就是它的活动范围在不断减小
  • 我们用x1,x2来表示行的上下边界;y1,y2来表示列的左右边界
  • 填充的行时,行坐标不变;填充列时,列坐标不变。
  • 在行边界,或者列坐标的边界重合时停止。
package zzc.leetCode;

import java.util.Arrays;
import java.util.Scanner;

public class test07 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		
		int m = in.nextInt();
		int n = in.nextInt(); 
		int r = in.nextInt();
		int c = in.nextInt();
		
		int[][] arra = new int[m][n];
		int[][] book = new int[m][n];
		
		//限定活动区域
		int x1 = 0, x2 = m - 1;
		int y1 = 0, y2 = n - 1;
		//填充数字
		int k = 1;
		//右下左上
		while(x1 <= x2 && y1 <= y2){
			//右
			for (int p = y1; p <= y2; p++) {
				if(book[x1][p] == 0){
					arra[x1][p] = k++;
					book[x1][p] = 1;
				}
			}
			x1++;
			//下
			for (int p = x1; p <= x2; p++) {
				if(book[p][y2] == 0){
					arra[p][y2] = k++;
					book[p][y2] = 1;
				}
			}
			y2--;
			//左
			for(int p = y2; p >= y1; p--){
				if(book[x2][p] == 0){
					arra[x2][p] = k++;
					book[x2][p] = 1;
				}
			}
			x2--;
			//上
			for(int p = x2; p >= x1; p--){
				if(book[p][y1] == 0){
					arra[p][y1] = k++;
					book[p][y1] = 1;
				}
			}
			y1++;
		}
//		for(int i = 0; i < m; i++){
//			System.out.println(Arrays.toString(arra[i]));
//		}
		System.out.println(arra[r - 1][c - 1]);
	}
}



第八题
 如果一个序列的奇数项都比前一项大,偶数项都比前一项小,则称为一个摆动序列。即 a[2i]a[2i]。
  小明想知道,长度为 m,每个数都是 1 到 n 之间的正整数的摆动序列一共有多少个。
输入格式
  输入一行包含两个整数 m,n。
输出格式
  输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。
样例输入
3 4
样例输出
14
样例说明
以下是符合要求的摆动序列:
  2 1 2
  2 1 3
  2 1 4
  3 1 2
  3 1 3
  3 1 4
  3 2 3
  3 2 4
  4 1 2
  4 1 3
  4 1 4
  4 2 3
  4 2 4
  4 3 4
法一: 在这之前需一个过渡:就是当m = 3,n = 4时,为了得到最终结果,我们可以这样做:

public static void main(String[] args) {
		int m = 3, n = 4;
		int sum = 0;
		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= n; j++){
				for(int k = 1; k <= n; k++){
					if(j < i && j < k){
//						System.out.println(i+" "+j+" "+k);
						sum++;
					}
				}
			}
		}
		System.out.println(sum);
	}

这样就能得出m = 3, n = 4时的答案,但是这里只用到了n = 4,m = 3并没有用到。细心的观察你会发现,有三个for循环。
大胆设想(超时)
要是m = 4呢。是不是应该出现四个for循环。要是m = 10呢。是不是有点深搜的味儿了。
能想到深搜基本就差不多了:这里的递归体并不难写,本人是难在了出口判断这个地方,数组越界想了我好长时间

package zzctst;

import java.util.Scanner;

public class test08 {
	
	static int ans = 0;
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		
		int m = in.nextInt();
		int n = in.nextInt();
		int[] arra = new int[m];
		f(arra, m , n, 0);
		System.out.println(ans);
	}
	static void f(int[] arra, int m, int n, int step){
		if(m == step){
			//检查
			boolean flag = true;
			//数组长度为偶数
			if(arra.length % 2 == 0){
				for (int i = 1; i < arra.length - 1; i++) {
					if(i % 2 != 0){
						if(arra[i] < arra[i - 1] && arra[i] < arra[i + 1]){
							continue;
						}else{
							flag = false;
							break;
						}
					}
					flag = flag && (arra[arra.length  - 1] < arra[arra.length  - 2]);
				}
			}else{
				//奇数
				for (int i = 1; i < arra.length; i+=2) {
					if(arra[i] < arra[i - 1] && arra[i] < arra[i + 1]){
						continue;
					}else{
						flag = false;
						break;	
					}
				}
			}
			if(flag){
//				for(int a : arra){
//					System.out.print(a + " ");
//				}
//				System.out.println();
				ans++;
			}
			return;
		}
		for(int i = 1; i <= n; i++){
			arra[step] = i;
			f(arra, m, n, step + 1);
		}
	}
}

法二:DP
2020年蓝桥杯省模拟赛_第2张图片

import java.util.Scanner;

public class 摆动序列 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int m = in.nextInt();
		int n = in.nextInt();
		//dp数组,第一列状态
		int[] dp = new int[n + 2];
		dp[0] = 0; dp[n] = 0;
		for(int i = 1; i < dp.length - 1; i++){
			dp[i] = 1;
		}
		
		System.out.println(f(dp, m, n));
	}
	static int f(int[] dp, int m, int n){
		//总数
		int sum = 0;
		//155033954
		for(int i = 2; i <= m ;i++){
			//中间夹的较小的一列
			if(i % 2 == 0){
				for(int j = 1; j <= dp.length - 2; j++){
					int tempSum = 0;
					for(int k = j + 1; k < dp.length; k++){
						tempSum += dp[k] % 10000;
					}
					dp[j] = tempSum; 
				}
			}else{
				for(int j = dp.length - 2; j >= 1; j--){
					int tempSum = 0;
					for(int k = j - 1; k >= 0; k--){
						tempSum += dp[k] % 10000;
					}
					dp[j] = tempSum; 
				}
			}
		}
		
		for(int k = 0; k < dp.length; k++)
			sum += dp[k] % 10000;
		
		return sum % 10000;
	}
}

第九题
小明和朋友们一起去郊外植树,他们带了一些在自己实验室精心研究出的小树苗。
  小明和朋友们一共有 n 个人,他们经过精心挑选,在一块空地上每个人挑选了一个适合植树的位置,总共 n 个。他们准备把自己带的树苗都植下去。
  然而,他们遇到了一个困难:有的树苗比较大,而有的位置挨太近,导致两棵树植下去后会撞在一起。
  他们将树看成一个圆,圆心在他们找的位置上。如果两棵树对应的圆相交,这两棵树就不适合同时植下(相切不受影响),称为两棵树冲突。
  小明和朋友们决定先合计合计,只将其中的一部分树植下去,保证没有互相冲突的树。他们同时希望这些树所能覆盖的面积和(圆面积和)最大。
输入格式
  输入的第一行包含一个整数 n ,表示人数,即准备植树的位置数。
  接下来 n 行,每行三个整数 x, y, r,表示一棵树在空地上的横、纵坐标和半径。
输出格式
  输出一行包含一个整数,表示在不冲突下可以植树的面积和。由于每棵树的面积都是圆周率的整数倍,请输出答案除以圆周率后的值(应当是一个整数)。
样例输入
6
1 1 2
1 4 2
1 7 2
4 1 2
4 4 2
4 7 2
样例输出
12

思路:(我感觉我能做对一部分,欢迎批评指正)

  • 按照半径由大到小排序,先种下覆盖面积最大的树a,然后取面积次大的树b,求a和b的圆心之间的距离len与半径之和rSum,len
  • 以此类推,我们创建数组tree[]来存放种到地面的树(保证面积两两不相交),想要种你手里这棵树,就必须先遍历tree[],手里这棵树与种下去的所有树面积不相交。
  • 没考虑的情况;如图:此时若是2,3的面积都和1相交,2,3不相交,2,3不和种上的树相交,但是2,3的面积之和大于1;我的算法显然就是抛弃了2,3,。这种情况得到的面积不是最大,还是求指点

2020年蓝桥杯省模拟赛_第3张图片

package zzctst;

import java.util.Scanner;

public class tset09 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[][] arra = new int[n][3];
		//存放能种下的树
		int[][] tree = new int[n][3];
		//接收树
		for(int i = 0; i < arra.length; i++){
			for(int j = 0; j < 3; j++){
				arra[i][j] = in.nextInt();
			}
		}
		f(arra, tree);
	}
	/**
	 * 统计能种下去的树的数量
	 * 保证两两之间的树aoe不相交,圆心之间的距离大于半径之和
	 * @param arra
	 */
	static void f(int[][] arra, int[][] tree){
		//数量
		int sum = 0;
		//面积之和
		int ans = 0;
		//由大到小排序
		sort(arra);
		//空地先放一棵面积最大树
		tree[0][0] = arra[0][0];
		tree[0][1] = arra[0][1];
		tree[0][2] = arra[0][2];
		ans += tree[0][2] * tree[0][2];
		sum++;
		//
		for(int i = 1; i < arra.length; i++){
			boolean flag = true;
			for(int j = 0; j < sum; j++){
				//圆心之间的距离
				double len = Math.sqrt(
						(tree[j][0] - arra[i][0]) * (tree[j][0] - arra[i][0]) + 
						(tree[j][1] - arra[i][1]) * (tree[j][1] - arra[i][1])
						        );
				//半径之和 
				double rSum = arra[i][2] + tree[j][2];
				//判断圆心之间的距离小于半径之和
				if(len < rSum){
					flag = false;
					break;
				}
			}
			if(flag){
				ans += arra[i][2] * arra[i][2];
				tree[sum][0] = arra[i][0];
				tree[sum][1] = arra[i][1];
				tree[sum][2] = arra[i][2];
				sum++;
			}
		}
		System.out.println(ans);
	}
	
	/**
	 * 根据种下去的面积由大到小排序
	 * @param arra
	 */
	static void sort(int[][] arra){
		for(int i = 0; i < arra.length - 1; i++){
			for(int j = 0; j < arra.length - 1 - i; j++){
				if(arra[j][2] < arra[j + 1][2]){
					int temp = arra[j][0];
					arra[j][0] = arra[j + 1][0];
					arra[j+1][0] = temp;
					
					temp = arra[j][1];
					arra[j][1] = arra[j + 1][1];
					arra[j+1][1] = temp;
					
					temp = arra[j][2];
					arra[j][2] = arra[j + 1][2];
					arra[j+1][2] = temp;
				}
			}
		}
	}
}

第十题(最小生成树)
 2015年,全中国实现了户户通电。作为一名电力建设者,小明正在帮助一带一路上的国家通电。
  这一次,小明要帮助 n 个村庄通电,其中 1 号村庄正好可以建立一个发电站,所发的电足够所有村庄使用。
  现在,这 n 个村庄之间都没有电线相连,小明主要要做的是架设电线连接这些村庄,使得所有村庄都直接或间接的与发电站相通。
  小明测量了所有村庄的位置(坐标)和高度,如果要连接两个村庄,小明需要花费两个村庄之间的坐标距离加上高度差的平方,形式化描述为坐标为 (x_1, y_1) 高度为 h_1 的村庄与坐标为 (x_2, y_2) 高度为 h_2 的村庄之间连接的费用为
  sqrt((x_1-x_2)(x_1-x_2)+(y_1-y_2)(y_1-y_2))+(h_1-h_2)*(h_1-h_2)。
  在上式中 sqrt 表示取括号内的平方根。请注意括号的位置,高度的计算方式与横纵坐标的计算方式不同。
  由于经费有限,请帮助小明计算他至少要花费多少费用才能使这 n 个村庄都通电。
输入格式
  输入的第一行包含一个整数 n ,表示村庄的数量。
  接下来 n 行,每个三个整数 x, y, h,分别表示一个村庄的横、纵坐标和高度,其中第一个村庄可以建立发电站。
输出格式
  输出一行,包含一个实数,四舍五入保留 2 位小数,表示答案。
样例输入
4
1 1 3
9 9 7
8 8 6
4 5 4
样例输出
17.41

你可能感兴趣的:(蓝桥杯)