2018年第九届蓝桥杯Java本科B组国赛题解

第一题

标题:三角形面积
已知三角形三个顶点在直角坐标系下的坐标分别为:
(2.3, 2.5)
(6.4, 3.1)
(5.1, 7.2)
求该三角形的面积。
注意,要提交的是一个小数形式表示的浮点数。
要求精确到小数后3位,如不足3位,需要补零。

代码
在这里插入图片描述
或者使用 海伦公式 p=(a+b+c)/2,S=Math.sqrt(p* (p-a)* (p-b)*(p-c))

import java.io.*;
import java.util.*;
/*
A(2.3, 2.5)
B(6.4, 3.1)
C(5.1, 7.2)
 */
public class Main
{
	public static void main(String[] args)
	{
		double a=Math.sqrt((5.1-6.4)*(5.1-6.4)+(7.2-3.1)*(7.2-3.1));
		double b=Math.sqrt((5.1-2.3)*(5.1-2.3)+(7.2-2.5)*(7.2-2.5));
		double c=Math.sqrt((6.4-2.3)*(6.4-2.3)+(3.1-2.5)*(3.1-2.5));
		double p=(a+b+c)/2;
		double result=Math.sqrt(p*(p-a)*(p-b)*(p-c));
		System.out.println(result);
	}
}

结果:8.795

第二题

标题:最大乘积
把 1~9 这9个数字分成两组,中间插入乘号,
有的时候,它们的乘积也只包含1~9这9个数字,而且每个数字只出现1次。
比如:
984672 * 351 = 345619872
98751 * 3462 = 341875962
9 * 87146325 = 784316925

符合这种规律的算式还有很多,请你计算在所有这些算式中,乘积最大是多少?
注意,需要提交的是一个整数,表示那个最大的积,不要填写任何多余的内容。
(只提交乘积,不要提交整个算式)

代码

import java.io.*;
import java.util.*;

public class Main
{
	public static int[] a=new int[9];//0-8
	public static int[] vis=new int[10];
	public static int[] test;
	public static long maxn=0;
	public static void main(String[] args)
	{
		vis[0]=1;
		dfs(0);
		System.out.println(maxn);
	}
	//判断乘积是否为1-9各个数只出现一次
	public static boolean judge(long result)
	{
		//test数组存储每个数出现的次数
		test=new int[10];
		while(result>0)
		{
			test[(int) (result%10)]++;
			result/=10;
		}
		//遍历test数组,如果存在某个数出现次数不为1,则返回false
		for(int i=1;i<=9;i++)
		{
			if(test[i]!=1)
			{
				return false;
			}
		}
		return true;	
	}
	public static void dfs(int index)
	{
		if(index==9)
		{
			long result;
			//遍历分割点
			for(int k=0;k<9;k++)
			{
				int num1=0,num2=0;
				//第一个乘数
				for(int i=0;i<=k;i++)
				{
					num1=num1*10+a[i];
				}
				//第二个乘数
				for(int i=k+1;i<9;i++)
				{
					num2=num2*10+a[i];
				}
				//获得乘积
				result=num1*num2;
				//如果乘积大于maxn,乘积位数为9位,且judge返回为true
				if(result>maxn&&String.valueOf(result).length()==9&&judge(result)) 
				{
					maxn=result;
				}
			}
		}
		//组成一个个各位数不同的9位数
		for(int i=9;i>0;i--)
		{
			if(vis[i]==0)
			{
				vis[i]=1;
				a[index]=i;
				dfs(index+1);
				vis[i]=0;
			}
		}
	}
}

结果:839542176

第三题

标题:全排列
对于某个串,比如:“1234”,求它的所有全排列。
并且要求这些全排列一定要按照字母的升序排列。
对于“1234”,应该输出(一共4!=24行):
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
下面是实现程序,请仔细分析程序逻辑,并填写划线部分缺少的代码。

import java.util.*;
public class A
{
	static void permu(char[] data, int cur){
		if(cur==data.length-1){
			System.out.println(new String(data));
			return;
		}
		
		for(int i=cur; i<data.length; i++){
			char tmp = data[i]; 
			for(int j=i-1; j>=cur; j--) data[j+1] = data[j];
			data[cur] = tmp;			
 
			permu(data, cur+1);			
 
			tmp = data[cur]; 
			__________________________________________ ;
			data[i] = tmp;			
		}
	}
	
	static void permu(String x){
		permu(x.toCharArray(),0);
	}
	
	public static void main(String[] args){
		permu("1234");
	}
}

填空结果:for(int j=cur;j<i;j++) data[j]=data[j+1]
有其他答案也符合题目要求,但感觉这个答案是比较准确的,仔细观察代码中的这几行,你就可以看出来

char tmp = data[i]; 
for(int j=i-1; j>=cur; j--) data[j+1] = data[j];
data[cur] = tmp;	
tmp = data[cur]; 
for(int j=cur; j<i; j++) data[j]=data[j+1];
data[i] = tmp;

输出结果:
在这里插入图片描述
第四题

标题:整理玩具
小明有一套玩具,一共包含NxM个部件。这些部件摆放在一个包含NxM个小格子的玩具盒中,每个小格子中恰好摆放一个部件。
每一个部件上标记有一个0~9的整数,有可能有多个部件标记相同的整数。
小明对玩具的摆放有特殊的要求:标记相同整数的部件必须摆在一起,组成一个矩形形状。
如以下摆放是满足要求的:

00022
00033
44444  

12244
12244
12233

01234
56789

以下摆放不满足要求:

11122
11122
33311

111111
122221
122221
111111

11122
11113
33333

给出一种摆放方式,请你判断是否符合小明的要求。
输入
输入包含多组数据。
第一行包含一个整数T,代表数据组数。 (1 <= T <= 10)
以下包含T组数据。
每组数据第一行包含两个整数N和M。 (1 <= N, M <= 10)
以下包含N行M列的矩阵,代表摆放方式。
输出
对于每组数据,输出YES或者NO代表是否符合小明的要求。
【样例输入】
3
3 5
00022
00033
44444
3 5
11122
11122
33311
2 5
01234
56789
【样例输出】
YES
NO
YES
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。

代码

import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
 
public class Main {
	public static boolean show(int[][] a,Set<Integer> set)
	{
		boolean result=true;
		Iterator<Integer> it=set.iterator();
		//依次获得每种部件编号的矩形区域
		while(it.hasNext())
		{ 
			int x1=0,x2=0,y1=0,y2=0;//起点(x1,y1),终点(x2,y2)
			int t=it.next();//每种部件编号
			int flag=0;//定义一个变量,判断是否是第一次出现
			for(int i=0;i<a.length;i++)
				for(int j=0;j<a[0].length;j++)
				{
					//第一次出现该编号
					if(a[i][j]==t&&flag==0)
					{
						x1=i;
						y1=j;
						x2=x1;
						y2=y1;
						flag=1;
					}
					//不是第一次出现,只需要改变终点
					else if(a[i][j]==t&&flag==1)
					{
						x2=i;
						y2=j;
					}
				}
			//判断该编号的矩形区域是否符合条件
			if(!judge(a,x1,y1,x2,y2,t))
			{
				result=false;
				break;
			}	
		}
		return result;
	}
	//判断是否符合条件
	public static boolean judge(int[][] a,int x1,int y1,int x2,int y2,int b)
	{
		for(int i=x1;i<a.length;i++)
			for(int j=y1;j<a[0].length;j++)
			{
				//如果在矩形范围外还存在等于b的部件,则返回false
				if(i<x1||i>x2||j<y1||j>y2)
				{
					if(a[i][j]==b)
						return false;
				}
				//如果在矩形内部存在不等于b的部件,则返回false
				else
				{
					if(a[i][j]!=b)
						return false;
				}
			}
		return true;
	}
	public static void main(String[] args)
	{
		Scanner scan = new Scanner(System.in);
		int t=scan.nextInt();
		while(t>0)
		{
			int n=scan.nextInt();
			int m=scan.nextInt();
			int[][] a=new int[n][m];
			//用set存储矩阵中出现的数字种类数
			Set<Integer> set=new HashSet<>();
			for(int i=0;i<n;i++)
			{
				String s=scan.next();
				for(int j=0;j<m;j++)
				{
					//a存储二维矩阵
					a[i][j]=s.toCharArray()[j]-'0';
					set.add(a[i][j]);//种类数
				}
			}
			boolean result=show(a,set);
			if(result==true)
				System.out.println("YES");
			else
				System.out.println("NO");
			set.clear();
			t--;
		}
		scan.close();
	}
}

第五题

标题:版本分支
小明负责维护公司一个奇怪的项目。这个项目的代码一直在不断分支(branch)但是从未发生过合并(merge)。
现在这个项目的代码一共有N个版本,编号1~N,其中1号版本是最初的版本。
除了1号版本之外,其他版本的代码都恰好有一个直接的父版本;即这N个版本形成了一棵以1为根的树形结构。
如下图就是一个可能的版本树:

    1
   / \
  2   3
  |  / \
  5 4   6

现在小明需要经常检查版本x是不是版本y的祖先版本。你能帮助小明吗?
输入
第一行包含两个整数N和Q,代表版本总数和查询总数。
以下N-1行,每行包含2个整数u和v,代表版本u是版本v的直接父版本。
再之后Q行,每行包含2个整数x和y,代表询问版本x是不是版本y的祖先版本。
对于30%的数据,1 <= N <= 1000 1 <= Q <= 1000
对于100%的数据,1 <= N <= 100000 1 <= Q <= 100000
输出
对于每个询问,输出YES或NO代表x是否是y的祖先。
【样例输入】
6 5
1 2
1 3
2 5
3 6
3 4
1 1
1 4
2 6
5 2
6 4
【样例输出】
YES
YES
NO
NO
NO
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。

代码

import java.io.*;
import java.util.*;
/*
因为刚做完2017年国赛题,看到这道题联想到了17年的第三题树形显示
 */
public class Main {
	public static Map<Integer,List<Integer>> map;
	//用递归求map
	public static void dfs(int index)
	{
		//获取该节点的直接孩子节点
		List<Integer> fin=map.get(index);
		//对于每个孩子节点,递归求其孩子节点
		for(int i=0;i<fin.size();i++)
		{
			//如果map中包含该孩子节点
			if(map.containsKey(fin.get(i)))
			{
				//将该孩子节点下的孩子节点添加到fin中
				fin.addAll(map.get(fin.get(i)));
				dfs(fin.get(i));
			}
		}
	}
	public static void main(String[] args) throws IOException
	{
		//map键为所有的父亲节点,值为每个父亲节点拥有的全部孩子
		//对于样例来说,即map为 {1=[2, 3, 5, 6, 4], 2=[5], 3=[6, 4]}
		map=new HashMap<Integer,List<Integer>>();
		//使用BufferedReader效率优于Scanner
		BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
		//读取输入并存储
		String[] a=reader.readLine().split(" ");
		int N=Integer.parseInt(a[0]);
		int Q=Integer.parseInt(a[1]);
		List<Integer> list;
		for(int i=0;i<N-1;i++)
		{
			String[] b=reader.readLine().split(" ");
			int u=Integer.parseInt(b[0]);
			int v=Integer.parseInt(b[1]);
			//如果该父亲节点不存在,则创建空list列表
			if(!map.containsKey(u))
			{
				list=new ArrayList<Integer>();
			}
			//如果存在则直接获得父亲节点对应的list列表
			else  list=map.get(u);
			//添加新的孩子节点
			list.add(v);
			map.put(u, list);
		}
		//递归求map
		dfs(1);
		//存储需判断的数据
		int[] x=new int[Q];
		int[] y=new int[Q];
		for(int i=0;i<Q;i++)
		{
			String[] c=reader.readLine().split(" ");
			x[i]=Integer.parseInt(c[0]);
			y[i]=Integer.parseInt(c[1]);
		}
		//逐行判断
		for(int i=0;i<Q;i++)
		{
			if(x[i]==y[i]) System.out.println("YES");
			else if(map.get(x[i])==null||map.get(x[i]).contains(y[i])==false)
				System.out.println("NO");
			else
				System.out.println("YES");
		}
	}
}

附加一组测试用例:
10 6
1 2
1 3
2 4
2 5
3 6
3 7
4 8
7 9
7 10
6 5
1 4
7 9
1 10
5 8
3 4
结果:
NO
YES
YES
YES
NO
NO

第六题

标题:防御力
小明最近在玩一款游戏。对游戏中的防御力很感兴趣。
我们认为直接影响防御的参数为“防御性能”,记作d,而面板上有两个防御值A和B,与d成对数关系,A=2d,B=3d(注意任何时候上式都成立)。
在游戏过程中,可能有一些道具把防御值A增加一个值,有另一些道具把防御值B增加一个值。
现在小明身上有n1个道具增加A的值和n2个道具增加B的值,增加量已知。
现在已知第i次使用的道具是增加A还是增加B的值,但具体使用那个道具是不确定的,请找到一个字典序最小的使用道具的方式,使得最终的防御性能最大。
初始时防御性能为0,即d=0,所以A=B=1。
【输入格式】
输入的第一行包含两个数n1,n2,空格分隔。
第二行n1个数,表示增加A值的那些道具的增加量。
第三行n2个数,表示增加B值的那些道具的增加量。
第四行一个长度为n1+n2的字符串,由0和1组成,表示道具的使用顺序。0表示使用增加A值的道具,1表示使用增加B值的道具。输入数据保证恰好有n1个0,n2个1。
【输出格式】
对于每组数据,输出n1+n2+1行,前n1+n2行按顺序输出道具的使用情况,若使用增加A值的道具,输出Ax,x为道具在该类道具中的编号(从1开始)。若使用增加B值的道具则输出Bx。最后一行输出一个大写字母E。

【样例输入1】
1 2
4
2 8
101
【样例输出1】
B2
A1
B1
E
【样例输入2】
3 0
7 11 13

000  
【样例输出2】 
A1 
A2 
A3 
E

【样例说明】
对于第一组测试数据,操作过程如下:
操作   d         A              B
初始   0         1              1
B2    2          4              9
A1    3          8              27
B1   log3(29)   2^(log3(29))    29

可以证明,这个值是最大的。 对于第二组测试数据,可见无论用什么顺序,A最后总为32,即d总为5,B总为243。
【数据规模】
对于20%的数据,字符串长度<=10000;
对于70%的数据,字符串长度<=200000;
对于100%的数据,字符串长度<=2000000,输入的每个增加值不超过2^30。
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。

代码

import java.io.*;
import java.util.*;

public class Main {
	static A[] a;
	static B[] b;
	//值相同按字典序排序(从小到大),否则按值从大到小排序
	static class A implements Comparable<A>
	{
		int id;
		int value;
		A(int a,int b)
		{
			id=a;value=b;
		}
		@Override
		public int compareTo(A o) {
			// TODO Auto-generated method stub
			if(o.value-value==0)
				return id-o.id;
			else
				return o.value-value;
		}
	}
	static class B implements Comparable<B>
	{
		int id;
		int value;
		B(int a,int b)
		{
			id=a;value=b;
		}
		@Override
		public int compareTo(B o) {
			// TODO Auto-generated method stub
			if(o.value-value==0)
				return id-o.id;
			else
				return o.value-value;
		}
	}
	
	public static void main(String[] args) throws IOException
	{
		BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
		String s1=reader.readLine();
		int n1=Integer.parseInt(s1.split(" ")[0]);
		int n2=Integer.parseInt(s1.split(" ")[1]);
		a=new A[n1+1];
		b=new B[n2+1];
		String[] sa=reader.readLine().split(" ");
		String[] sb=reader.readLine().split(" ");
		char[] s=reader.readLine().toCharArray();
		for(int i=1;i<=n1;i++) 
		{
			int id=i;
			int value=Integer.parseInt(sa[i-1]);
			a[i]=new A(id,value);
		}
		for(int i=1;i<=n2;i++)
		{
			int id=i;
			int value=Integer.parseInt(sb[i-1]);
			b[i]=new B(id,value);
		}
		//排序
		Arrays.sort(a,1,n1+1);
		Arrays.sort(b,1,n2+1);
		int countA=1,countB=1;
		int[] temp;
		for(int i=0;i<n1+n2;i++)
		{
			if(s[i]=='1')//当前为1
			{
				if(i+1==n1+n2||s[i+1]=='0')//只有一个1
					System.out.println("B"+b[countB++].id);
				else//出现连续个1
				{
					int k=0;
					int j;
					temp=new int[s.length-i+5];
					//将连续的1的id号存入temp数组中
					for(j=i;j<n1+n2;j++)
					{
						if(s[j]!='1') break;
						temp[k++]=b[countB++].id;
					}
					//对temp数组按字典序从小到大排序
					Arrays.sort(temp,0,k);
					i=j-1;
					for(j=0;j<k;j++)
					{
						System.out.println("B"+temp[j]);
					}
				}
			}
			else//当前为0
			{
				if(i+1==n1+n2||s[i+1]=='1')//只有一个0
					System.out.println("A"+a[countA++].id);
				else//出现连续个0
				{
					int k=0;
					int j;
					temp=new int[s.length-i+5];
					for(j=i;j<n1+n2;j++)
					{
						if(s[j]!='0') break;
						temp[k++]=a[countA++].id;
					}
					Arrays.sort(temp,0,k);
					i=j-1;
					for(j=0;j<k;j++)
					{
						System.out.println("A"+temp[j]);
					}
				}
			}	
		}
		System.out.println("E");
	}
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值