编程语言
首页 > 编程语言> > 2016年第七届蓝桥杯javaB组 试题 答案 解析

2016年第七届蓝桥杯javaB组 试题 答案 解析

作者:互联网

目录

1.煤球数目

public class One {
	
	public static void main(String[] args) {
		int sum = 0;
		for(int i = 1; i <= 100; i++){
			sum += count(i);
		}
		System.out.println(sum);
	}
	
	public static int count(int num){
		int sum = 0;
		for(int i = 1; i <= num; i++){
			sum += i;
		}
		return sum;
	}
}

答案: 171700

 


2.生日蜡烛

public class Main {
	
	public static void main(String[] args) {
		for(int i = 1; ; i++){
			if(process(i) == -1){
				continue;
			}else{
				System.out.println(i);
				return;
			}
		}
		
	}
	
	public static int process(int n){
		int sum = 0;
		for(int i = n;; i++){
			sum += i;
			if(sum == 236){
				return n;
			}else if(sum > 236){
				return -1;
			}
		}
	}
}

答案: 26

 


3.凑算式

     B      DEF
A + --- + ------- = 10
     C      GHI
public class Main {
	
	public static float[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
	public static int res = 0;
	
	public static void main(String[] args) {
		process(0);
		System.out.println(res);
	}
	
	public static void process(int index){
		if(index == arr.length){
			check();
			return;
		}
		for(int i = index; i < arr.length; i++){
			swap(i, index);
			process(index + 1);
			swap(i, index);
		}
	}
	
	public static void check(){
		float jiaShu = arr[0];
		float fenZi1 = arr[1];
		float fenMu1 = arr[2];
		float fenZi2 = arr[3] * 100 + arr[4] * 10 + arr[5];
		float fenMu2 = arr[6] * 100 + arr[7] * 10 + arr[8];
		if(jiaShu + (fenZi1 / fenMu1) + (fenZi2 / fenMu2) == 10){
			res++;
		}
	}
	
	public static void swap(int i, int j){
		float temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
}

答案: 29

 


4. 分小组

该程序的正常输出为:
ABC DEF GHI
ABC DEG FHI
ABC DEH FGI
ABC DEI FGH
ABC DFG EHI
ABC DFH EGI
ABC DFI EGH
ABC DGH EFI
ABC DGI EFH
ABC DHI EFG
ABC EFG DHI
ABC EFH DGI
ABC EFI DGH
ABC EGH DFI
ABC EGI DFH
ABC EHI DFG
ABC FGH DEI
ABC FGI DEH
ABC FHI DEG
ABC GHI DEF
ABD CEF GHI
ABD CEG FHI
ABD CEH FGI
ABD CEI FGH
ABD CFG EHI
ABD CFH EGI
ABD CFI EGH
ABD CGH EFI
ABD CGI EFH
ABD CHI EFG
ABD EFG CHI
..... (以下省略,总共560行)。

public class A
{
	public static String remain(int[] a)
	{
		String s = "";
		for(int i=0; i<a.length; i++){
			if(a[i] == 0) s += (char)(i+'A');
		}	
		return s;
	}
	
	public static void f(String s, int[] a)
	{
		for(int i=0; i<a.length; i++){
			if(a[i]==1) continue;
			a[i] = 1;
			for(int j=i+1; j<a.length; j++){
				if(a[j]==1) continue;
				a[j]=1;
				for(int k=j+1; k<a.length; k++){
					if(a[k]==1) continue;
					a[k]=1;
					System.out.println(__________________________________);  //填空位置
					a[k]=0;
				}
				a[j]=0;
			}
			a[i] = 0;
		}
	}
	
	public static void main(String[] args)
	{
		int[] a = new int[9];		
		a[0] = 1;
		
		for(int b=1; b<a.length; b++){
			a[b] = 1;
			for(int c=b+1; c<a.length; c++){
				a[c] = 1;
				String s = "A" + (char)(b+'A') + (char)(c+'A');
				f(s,a);
				a[c] = 0;
			}
			a[b] = 0;
		}
	}
}

答案: s + " " + (char)(i + 'A') + (char)(j + 'A') + (char)(k + 'A') + " " + remain(a)

 


5.抽签

DEFFF
CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF
....
(以下省略,总共101行)


public class A
{
	public static void f(int[] a, int k, int n, String s)
	{
		if(k==a.length){ 
			if(n==0) System.out.println(s);
			return;
		}
		
		String s2 = s;
		for(int i=0; i<=a[k]; i++){
			_____________________________;   //填空位置
			s2 += (char)(k+'A');
		}
	}
	
	public static void main(String[] args)
	{
		int[] a = {4,2,2,1,1,3};
		
		f(a,0,5,"");
	}
}

答案: f(a, k + 1, n - i, s2);

 


6.方格填数

   +--+--+--+
   |  |  |  |
+--+--+--+--+
|  |  |  |  |
+--+--+--+--+
|  |  |  |
+--+--+--+

这道题的递归策略类似八皇后问题, 也就说当来到第一个格子后, 下一个要填的数不是连接着下一个位置的, 也就是说每个位置要填的数字来自于整个样本, 而且要注意回溯, 保证其他递归过程没有出错.

public class Six {
	
	public static int[][] dp = new int[5][6];
	public static int[] arr = new int[10];
	public static int res = 0;
	
	public static void main(String[] args) {
		initDp();
		process(1, 2);
		System.out.println(res);
	}
	
	public static void process(int x, int y){
		if(x == 3 && y == 4){
			res++;
			return;
		}
		for(int n = 0; n <= 9; n++){
			if(arr[n] == 0 && canFill(x, y, n)){
				dp[x][y] = n;
				arr[n] = 1;
				if(y == 4){
					process(x + 1, 1);
				}else{
					process(x, y + 1);
				}
				arr[n] = 0;
				dp[x][y] = -11;
			}
		}
	}
	
	public static boolean canFill(int x, int y, int n){
		boolean ans = true;
		for(int i = -1; i <= 1; i++){
			for(int j = -1; j <= 1; j++){
				if(i == 0 && j == 0) continue;
				if(Math.abs(dp[x + i][y + j] - n) <= 1){
					ans = false;
				}
			}
		}
		return ans;
	}
	
	public static void initDp(){
		for(int i = 0; i < 5; i++){
			for(int j = 0; j < 6; j++){
				dp[i][j] = -11;
			}
		}
	}
}

答案: 1580

 


7.剪邮票

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

首先通过5层for循环枚举选出5数, 难点在于判断这5个数是否是相连的, 可以利用图中标有编号的特性进行判断. 可以直观地看到一个数上面联通的数可-4得到, 下面的数可+4得到, 同理左边是-1, 右边是+1. 但是, 有特殊情况, 比如4+1为5, 理论上4的右边是5, 但是由于换行的原因, 4和5不是联通的. 但是这个方法是好的, 可以通过修改图中的编号继续使用这个方法.

可以把图改成: 
1  2  3  4 
6  7  8  9
10 11 12 13
public class Seven {

	public static int res = 0;
	public static int[] arr = {1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14};
	public static int[] p = new int[5];
	public static boolean[] visit = new boolean[5];
	public static int[] c = {5, -5, 1, -1};
	
	public static void main(String[] args) {
		for(int a = 0; a < 12; a++){
			for(int b = a + 1; b < 12; b++){
				for(int c = b + 1; c < 12; c++){
					for(int d = c + 1; d < 12; d++){
						for(int e = d + 1; e < 12; e++){
							p[0] = arr[a];
							p[1] = arr[b];
							p[2] = arr[c];
							p[3] = arr[d];
							p[4] = arr[e];
							process(0);
							boolean flag = true;
							for(int i = 0; i < 5; i++){
								if(!visit[i]){
									flag = false;
								}
							}
							if(flag){
								res++;
							}
							cleanVisit();
						}
					}
				}
			}
		}
		System.out.println(res);
	}
	
	public static void process(int n){
		for(int i = 0; i < 4; i++){
			int t = p[n] + c[i];
			if(t < 1 || t > 14 || t == 5 || t == 10){
				continue;
			}
			for(int j = 0; j < 5; j++){
				if(!visit[j] && p[j] == t){
					visit[j] = true;
					process(j);
				}
			}
		}
	}
	
	public static void cleanVisit(){
		for(int i = 0; i < 5; i++){
			visit[i] = false;
		}
	}
}

答案: 116

 


8.四平方和

例如,输入:
5
则程序应该输出:
0 0 1 2

再例如,输入:
12
则程序应该输出:
0 2 2 2

再例如,输入:
773535
则程序应该输出:
1 1 267 838

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 3000ms

这道题是常规的暴力枚举题, 难在如何降低时间复杂度跑过所有的用例, 如果a, b, c, d每个数都穷举以便, 按照最大的输入5000000, 每个数要枚举的次数为10^3级, 一共就是10^12. 太大了, 会超时. 为了能减少次数, 把枚举分成两半, 一半的数据是a * a + b * b, 这一半的数据用哈希表存储, 另外一半的数据是c * c + d * d = n - a * a + b * b. 这样能把枚举的规模缩小一半.

public class Eight {
	
	static HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		
		for(int c = 0; c * c <= n / 2; c++){
			for(int d = c; c * c + d * d <= n; d++){
				if(!map.containsKey(c * c + d * d)){
					map.put(c * c + d * d, c);
				}
			}
		}
		for(int a = 0; a * a <= n / 4; a++){
			for(int b = a; a * a + b * b <= n; b++){
				if(map.containsKey(n - a * a - b * b)){
					int c = map.get(n - a * a - b * b);
					int d = (int) Math.sqrt(n - a * a - b * b - c * c);
					System.out.println(a + " " + b + " " + c + " " + d);
					return;
				}
			}
		}
	}}

 


9.取球博弈

例如,输入:
1 2 3
1 2 3 4 5

程序应该输出:
+ 0 + 0 -

再例如,输入:
1 4 5
10 11 12 13 15

程序应该输出:
0 - 0 + +

再例如,输入:
2 3 5
7 8 9 10 11

程序应该输出:
+ 0 0 0 0

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 3000ms

思路

32520
public class QuQiuBoYi {
	
	public static int[] n = new int[3];
	public static int[] m = new int[5];
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		for(int i = 0; i < 3; i++){
			n[i] = sc.nextInt();
		}
		Arrays.sort(n);
		for(int i = 0; i < 5; i++){
			m[i] = sc.nextInt();
			char res = process(m[i], 0, 0);//每输入一局的球数, 就计算一局
			System.out.print(res + " ");
		}
	}
	
	public static char process(int num, int me, int you){
		if(num < n[0]){//没球可摸,进行结算
			if((me & 1) != 0 && (you & 1) == 0){//我奇数, 对手偶数, 赢
				return '+';
			}else if((me & 1) == 0 && (you & 1) != 0){//我偶数, 对手奇数, 输
				return '-';
			}else{
				return '0';//平
			}
		}
		boolean draw = false;
		for(int i = 0; i < 3; i++){
			if(num >= n[i]){
				//重点!假设当前这轮是我摸球, 在我摸完球me+n[i]后, 就到对手摸, me和you的位置转换, 设定中间的参数是摸球的一方
				char res = process(num - n[i], you, me + n[i]);
				if(res == '-'){//由于下一轮是对手摸球, 如果他输了
					return '+';//我就赢了
				}else if(res == '0'){//如果有平局, 要记录下来
					draw = true;
				}
			}
		}
		return draw ? '0' : '-';
	}
}

优化

public class Nine {
	
	public static int[] n = new int[3];
	public static int[] m = new int[5];
	public static char[][][] cache = new char[1000][2][2];
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		for(int i = 0; i < 3; i++){
			n[i] = sc.nextInt();
		}
		Arrays.sort(n);
		for(int i = 0; i < 5; i++){
			m[i] = sc.nextInt();
			char res = process(m[i], 0, 0);
			System.out.print(res + " ");
		}
	}
	
	public static char process(int num, int me, int you){
		if(num < n[0]){
			if((me & 1) != 0 && (you & 1) == 0){
				return '+';
			}else if((me & 1) == 0 && (you & 1) != 0){
				return '-';
			}else{
				return '0';//平
			}
		}
		if(cache[num][me][you] != '\0'){
			return cache[num][me][you]; 
		}
		boolean draw = false;
		for(int i = 0; i < 3; i++){
			if(num >= n[i]){
				char res = process(num - n[i], you, ((me + n[i]) & 1) == 0 ? 0 : 1);//只记录奇偶情况
				if(res == '-'){
					cache[num][me][you] = '+';
					return '+';
				}else if(res == '0'){
					draw = true;
				}
			}
		}
		if(draw){
			cache[num][me][you] = '0';
			return '0';
		}else{
			cache[num][me][you] = '-';
			return '-';
		}
	}
}

 


10.压缩变换

输入格式:
输入第一行包含一个整数n,表示序列的长度。
第二行包含n个正整数,表示输入序列。

输出格式:
输出一行,包含n个数,表示变换后的序列。

例如,输入:
5
1 2 2 1 2

程序应该输出:
-1 -2 0 1 1

再例如,输入:
12
1 1 2 3 2 3 1 2 2 2 3 1

程序应该输出:
-1 0 -2 -3 1 1 2 2 0 0 2 2

数据规模与约定
对于30%的数据,n<=1000;
对于50%的数据,n<=30000;
对于100%的数据,1 <=n<=100000,1<=ai<=10^9

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 3000ms

按照题目的思路, 使用HashMap记录数的下标, 使用HashSet记录不同种的的数字, 时间复杂度O(N^2), 暴力做法能得30分.

public class Ten {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] arr = new long[n];
		for(int i = 0; i < arr.length; i++){
			arr[i] = sc.nextInt();
		}
		long[] former = Arrays.copyOf(arr, arr.length);
		HashMap<Long, Integer> map = new HashMap<Long, Integer>();
		for(int i = 0; i < arr.length; i++){
			if(!map.containsKey(arr[i])){
				map.put(arr[i], i);
				arr[i] = -arr[i];
			}else{
				int types = getTypes(map.get(arr[i]), i, former);
				map.put(arr[i], i);
				arr[i] = types;
			}
		}
		for(int i = 0; i < arr.length; i++){
			System.out.print(arr[i] + " ");
		}
	}
	
	public static int getTypes(int begin, int last, long[] former){
		HashSet<Long> set = new HashSet<Long>();
		int index = begin + 1;
		while(index < last){
			set.add(former[index++]);
		}
		return set.size();
	}
}

优化

标签:arr,ABC,javaB,int,蓝桥,++,static,2016,public
来源: https://blog.51cto.com/u_14797091/2758892