第八届蓝桥杯JavaB组国(决)赛真题
解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论
题目1、平方十位数题目描述
由0~9这10个数字不重复、不遗漏,可以组成很多10位数字。
这其中也有很多恰好是平方数(是某个数的平方)。
比如:1026753849,就是其中最小的一个平方数。
请你找出其中最大的一个平方数是多少?
注意:你需要提交的是一个10位数字,不要填写任何多余内容。
public class Main {
public static void main(String[] args) {
for (long i = 100000; i > 32000; i--) {
long sqrt = i * i;
String s = String.valueOf(sqrt);
boolean b = true;
for (int j = 0; j < 10; j++) {
if (s.indexOf("" + j) == -1) {
b = false;
break;
}
}
if (b) {
System.out.println(i * i);
break;
}
}
}
}
题目2、生命游戏
题目描述
康威生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
这个游戏在一个无限大的2D网格上进行。
初始时,每个小方格中居住着一个活着或死了的细胞。
下一时刻每个细胞的状态都由它周围八个格子的细胞状态决定。
具体来说:
1. 当前细胞为存活状态时,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
2. 当前细胞为存活状态时,当周围有2个或3个存活细胞时, 该细胞保持原样。
3. 当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
4. 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。 (模拟繁殖)
当前代所有细胞同时被以上规则处理后, 可以得到下一代细胞图。按规则继续处理这一代的细胞图,可以得到再下一代的细胞图,周而复始。
例如假设初始是:(X代表活细胞,.代表死细胞)
.....
.....
.XXX.
.....
下一代会变为:
.....
..X..
..X..
..X..
.....
康威生命游戏中会出现一些有趣的模式。例如稳定不变的模式:
....
.XX.
.XX.
....
还有会循环的模式:
...... ...... ......
.XX... .XX... .XX...
.XX... .X.... .XX...
...XX. -> ....X. -> ...XX.
...XX. ...XX. ...XX.
...... ...... ......
本题中我们要讨论的是一个非常特殊的模式,被称作"Gosper glider gun":
......................................
.........................X............
.......................X.X............
.............XX......XX............XX.
............X...X....XX............XX.
.XX........X.....X...XX...............
.XX........X...X.XX....X.X............
...........X.....X.......X............
............X...X.....................
.............XX.......................
......................................
假设以上初始状态是第0代,请问第1000000000(十亿)代一共有多少活着的细胞?
注意:我们假定细胞机在无限的2D网格上推演,并非只有题目中画出的那点空间。
当然,对于遥远的位置,其初始状态一概为死细胞。
注意:需要提交的是一个整数,不要填写多余内容。
package 生命游戏;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
public class Main {
//文件终止符问题, 点出去再点进来,无语。。。。。
static int[][] dir = {{1,-1},{1,1},{-1,1},{-1,-1},{0,1},{0,-1},{1,0},{-1,0}};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Map<Integer, HashSet> lifemap = new HashMap<>();//记录本轮生命体
Map<Integer, HashSet> nmap = new HashMap<>();//记录下一轮生命体
Map<Integer, HashSet> visit = new HashMap<>();//在每一轮中记录是否被访问过
//初始化
int row = 0;//y的值
String str;
//处理输入
while(sc.hasNext()) {
str = sc.nextLine();
for(int x = 0; x < str.length(); x++) {
if(str.charAt(x) == ‘X’) {
if(lifemap.containsKey(x)) {//把这个点加到map里
lifemap.get(x).add(row);
}else {
HashSet nset = new HashSet<>();
nset.add(row);
lifemap.put(x, nset);
}
}
}
row++;
}
int fans = 0;
for(Integer x : lifemap.keySet()) {
for(Integer y : lifemap.get(x)) {
//System.out.println(x + " " + y);
fans++;
}
}
System.out.println(fans);
//模拟游戏
int cnt = 0;
while(cnt < 100) {
for(Integer x : lifemap.keySet()) {//第一轮
for(Integer y : lifemap.get(x)) {
if(visit.containsKey(x)) //在某个点周围被先访问了,直接跳过
if(visit.get(x).contains(y))
continue;
if(visit.containsKey(x)) {//把这个点标记已访问
visit.get(x).add(y);
}else {
HashSet<Integer> nset = new HashSet<>();
nset.add(y);
visit.put(x, nset);
}
int num = 0;
//System.out.print(x + " " + y + " : ");
for(int[] d : dir) {//周围八个点,第一层
int curx = x + d[0];
int cury = y + d[1];
boolean alive = false;
if(lifemap.containsKey(curx))
if(lifemap.get(curx).contains(cury)) {
num++;
alive = true;
}
if(alive)
continue;
//System.out.print(curx + " " + cury + " : ");
if(visit.containsKey(curx)) //如果被访问过,就跳过这个点
if(visit.get(curx).contains(cury))
continue;
if(visit.containsKey(curx)) {//把这个点标记已访问
visit.get(curx).add(cury);
}else {
HashSet<Integer> nset = new HashSet<>();
nset.add(cury);
visit.put(curx, nset);
}
int cnum = 0;
for(int[] cd : dir) {//周围8个点,第二层
int cx = curx + cd[0];
int cy = cury + cd[1];
if(lifemap.containsKey(cx))
if(lifemap.get(cx).contains(cy)) {
cnum++;
}
}
//System.out.print(cnum);
//System.out.println();
if(cnum == 3) {
if(nmap.containsKey(curx)) {//把这个点加到map里
nmap.get(curx).add(cury);
}else {
HashSet<Integer> nset = new HashSet<>();
nset.add(cury);
nmap.put(curx, nset);
}
}
}
//System.out.print(num);
//System.out.println();
if(num < 2) {
;
}else if(num >=2 && num <= 3) {
if(nmap.containsKey(x)) {
nmap.get(x).add(y);
}else {
HashSet<Integer> nset = new HashSet<>();
nset.add(y);
nmap.put(x, nset);
}
}else{
;
}
}
}
lifemap = new HashMap<>();
lifemap.putAll(nmap);
nmap.clear();
visit.clear();
cnt++;
int ans = 0;
for(Integer x : lifemap.keySet()) {
for(Integer y : lifemap.get(x)) {
//System.out.println(x + " " + y);
ans++;
}
}
System.out.println(ans);
}
sc.close();
}
}
题目3、树型显示题目描述
对于分类结构可以用树形来形象地表示。比如:文件系统就是典型的例子。
树中的结点具有父子关系。我们在显示的时候,把子项向右缩进(用空格,不是tab),并添加必要的连接线,以使其层次关系更醒目。
下面的代码就是为了这个目的的,请仔细阅读源码,并填写划线部分缺少的代码。
import java.util.*;
class MyTree
{
private Map<String, List<String>> map_ch = new HashMap<String, List<String>>();
private Map<String,String> map_pa = new HashMap<String,String>();
public void add(String parent, String child)
{
map_pa.put(child, parent);
List<String> lst = map_ch.get(parent);
if(lst==null){
lst = new ArrayList<String>();
map_ch.put(parent, lst);
}
lst.add(child);
}
public String get_parent(String me){
return map_pa.get(me);
}
public List<String> get_child(String me){
return map_ch.get(me);
}
private String space(int n)
{
String s = "";
for(int i=0; i<n; i++) s += ' ';
return s;
}
private boolean last_child(String x){
String pa = map_pa.get(x);
if(pa==null) return true;
List<String> lst = map_ch.get(pa);
return lst.get(lst.size()-1).equals(x);
}
public void show(String x){
String s = "+--" + x;
String pa = x;
while(true){
pa = map_pa.get(pa);
if(pa==null) break;
s = ___________________________________ ; // 填空 s = (last_child(pa) ? " " : "|") + space(4) + s;
}
System.out.println(s);
}
public void dfs(String x){
show(x);
List<String> lst = map_ch.get(x);
if(lst==null) return;
for(String it: lst){
dfs(it);
}
}
}
public class TreeView
{
public static void main(String[] args)
{
MyTree tree = new MyTree();
tree.add("root", "dog");
tree.add("root", "cat");
tree.add("root", "duck");
tree.add("dog", "AAdog");
tree.add("dog", "BBdog");
tree.add("dog", "CCdog");
tree.add("AAdog", "AAdog01");
tree.add("AAdog", "AAdog02");
tree.add("cat", "XXcat");
tree.add("cat", "YYcat");
tree.add("XXcat","XXcat-oo");
tree.add("XXcat","XXcat-qq");
tree.add("XXcat-qq", "XXcat-qq-hahah");
tree.add("duck", "TTduck");
tree.add("TTduck", "TTduck-001");
tree.add("TTduck", "TTduck-002");
tree.add("TTduck", "TTduck-003");
tree.add("YYcat","YYcat.hello");
tree.add("YYcat","YYcat.yes");
tree.add("YYcat","YYcat.me");
tree.dfs("root");
}
}
输出结果为
s = (last_child(pa) ? " " : "|") + space(4) + s;
题目4、小计算器
题目描述
模拟程序型计算器,依次输入指令,可能包含的指令有
- 数字:‘NUM X’,X为一个只包含大写字母和数字的字符串,表示一个当前进制的数
- 运算指令:‘ADD’,‘SUB’,‘MUL’,‘DIV’,‘MOD’,分别表示加减乘,除法取商,除法取余
- 进制转换指令:‘CHANGE K’,将当前进制转换为K进制(2≤K≤36)
- 输出指令:‘EQUAL’,以当前进制输出结果
- 重置指令:‘CLEAR’,清除当前数字
指令按照以下规则给出:
数字,运算指令不会连续给出,进制转换指令,输出指令,重置指令有可能连续给出
运算指令后出现的第一个数字,表示参与运算的数字。且在该运算指令和该数字中间不会出现运算指令和输出指令
重置指令后出现的第一个数字,表示基础值。且在重置指令和第一个数字中间不会出现运算指令和输出指令
进制转换指令可能出现在任何地方
运算过程中中间变量均为非负整数,且小于2^63。
以大写的’A’'Z’表示1035
[输入格式]
第1行:1个n,表示指令数量
第2…n+1行:每行给出一条指令。指令序列一定以’CLEAR’作为开始,并且满足指令规则
[输出格式]
依次给出每一次’EQUAL’得到的结果
[样例输入]
7
CLEAR
NUM 1024
CHANGE 2
ADD
NUM 100000
CHANGE 8
EQUAL
[样例输出]
2040
补充说明:
- n 值范围: 1<= n < 50000
- 初始默认的进制是十进制
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
import java.util.Scanner;
public class Main3
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int jinZhi = 10;
int x = 0;
String yunSuan = "ADD";
scanner.nextLine();
for(int i=0;i<n;i++)
{
String string = scanner.nextLine();
if(string.indexOf("CLEAR")!=-1)x=0;
else if(string.indexOf("NUM")!=-1){
string = string.split(" ")[1];
if(yunSuan.indexOf("ADD")!=-1)x += Integer.parseInt(string, jinZhi);
else if(yunSuan.indexOf("SUB")!=-1)x -= Integer.parseInt(string, jinZhi);
else if(yunSuan.indexOf("MUL")!=-1)x *= Integer.parseInt(string, jinZhi);
else if(yunSuan.indexOf("DIV")!=-1)x /= Integer.parseInt(string, jinZhi);
else if(yunSuan.indexOf("MOD")!=-1)x %= Integer.parseInt(string, jinZhi);
}
else if(string.indexOf("ADD")!=-1)
{
yunSuan = "ADD";
}
else if(string.indexOf("SUB")!=-1)
{
yunSuan = "SUB";
}
else if(string.indexOf("MUL")!=-1)
{
yunSuan = "MUL";
}
else if(string.indexOf("DIV")!=-1)
{
yunSuan = "DIV";
}
else if(string.indexOf("MOD")!=-1)
{
yunSuan = "MOD";
}
else if(string.indexOf("CHANGE")!=-1)
{
string = string.split(" ")[1];
jinZhi = Integer.parseInt(string);
}
else if(string.indexOf("EQUAL")!=-1)
{
System.out.println(Integer.toString(x, jinZhi));
}
else if(string.indexOf("CLEAR")!=-1)
{
x=0;
yunSuan="ADD";
}
}
}
}
题目5、填字母游戏
题目描述
小明经常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说:
“我们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了”。
K大师在纸上画了一行n个格子,要小明和他交替往其中填入字母。
并且:
1. 轮到某人填的时候,只能在某个空格中填入L或O
2. 谁先让字母组成了“LOL”的字样,谁获胜。
3. 如果所有格子都填满了,仍无法组成LOL,则平局。
小明试验了几次都输了,他很惭愧,希望你能用计算机帮他解开这个谜。
本题的输入格式为:
第一行,数字n(n<10),表示下面有n个初始局面。
接下来,n行,每行一个串,表示开始的局面。
比如:“******”, 表示有6个空格。
“L****”, 表示左边是一个字母L,它的右边是4个空格。
要求输出n个数字,表示对每个局面,如果小明先填,当K大师总是用最强着法的时候,小明的最好结果。
1 表示能赢
-1 表示必输
0 表示可以逼平
例如,
输入:
4
***
L**L
L**L***L
L*****L
则程序应该输出:
0
-1
1
1
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
class Main{
static String str;
static Map<String, Integer>map=new HashMap<>();
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
int n=s.nextInt();
str=s.nextLine();
long currentTimeMillis = System.currentTimeMillis();
for(int i=0;i<n;i++)
{
str=s.nextLine();
System.out.println(adv());//-1 -1 1 L***L***L
}
// System.out.println(System.currentTimeMillis()-currentTimeMillis);
}
private static int adv() {//预处理
int index=0;
int a,b,len1 = 0,len2=0;
index=str.indexOf("*L*");
if(index>0)
{
String temp=str;
str=temp.substring(0,index+2);
for(int i=0;i<str.length();i++)
if(str.charAt(i)=='*')
len1++;
a=f();
str=temp.substring(index+1);
for(int i=0;i<str.length();i++)
if(str.charAt(i)=='*')
len2++;
b=f();
str=temp;
return u(a, b, len1, len2);
}else
{
return f();
}
}
private static int u(int a,int b,int len1,int len2)
{
if((a==1&&len1==1)||(b==1&&len2==1))
return 1;
if(a==1&&b==1)
return -1;
if(a==b)
return a;
if(a!=0&&b!=0)
return 1;
if(a==1||b==1)
return 1;
if(a==-1&&b==0)
return (len2%2==0)?a:-a;
if(a==0&&b==-1)
return (len1%2==0)?b:-b;
if(a==1&&b==0)
{
if(len1==1)return 1;
return (len2%2==0)?a:-a;
}
if(len2==1) return 1;
return (len1%2==0)?b:-b;
}
private static int f() {
if(str.contains("*OL")||str.contains("L*L")||str.contains("LO*"))
return 1;//终止条件
if(!str.contains("*"))
return 0;
//如果L****或者*****L
if((str.startsWith("L***")&&!str.substring(1).contains("O")&&!str.substring(1).contains("L"))
||
(str.endsWith("***L")&&!str.substring(0,str.length()-1).contains("O")&&!str.substring(0,str.length()-1).contains("L")))
return (str.length()%2==0)?1:-1;
List<Integer> indexs=index(str);//返回*号下标数组
int [] result=new int[indexs.size()*2];
int k=0;
for(int i=0;i<indexs.size();i++)
{
//换
str=rep(str, indexs.get(i), 'L');
if(map.containsKey(tri(str))){
result[k++]=map.get(tri(str));
}else{
map.put(tri(str),result[k++]=f());
}
if(result[k]==-1)
{
str=rep(str, indexs.get(i), '*');
return 1;
}
str=rep(str, indexs.get(i), 'O');
if(map.containsKey(tri(str))){
result[k++]=map.get(tri(str));
}else{
map.put(tri(str),result[k++]=f());
}
if(k<result.length&&result[k]==-1)
{
str=rep(str, indexs.get(i), '*');
return 1;
}
str=rep(str, indexs.get(i), '*');
}
return vote(result);
}
private static String tri(String str)
{
int start=str.indexOf('*');
int end=str.lastIndexOf('*');
if(start-2<0) start=2;
if(end+3>=str.length()) end=str.length()-3;
str=str.substring(start-2,end+3);
if(str.startsWith("OL*")||str.startsWith("OO*")||str.startsWith("LL*"))
str=str.substring(1);
if(str.endsWith("*LO ")||str.endsWith("*OO")||str.endsWith("*LL"))
str=str.substring(0,str.length()-1);
return str;
}
//replace函数
private static String rep(String str,int index,char a)
{
return str.substring(0,index)+a+str.substring(index+1);
}
//vote函数(全为1返回-1,有一个-1返回1)
private static int vote(int []a)
{
int min=1;
for(int i=0;i<a.length;i++)
{
min=min<a[i]?min:a[i];
}
return 0-min;
}
//返回*下标数组
private static List index(String nextLine) {
List<Integer> list=new ArrayList<Integer>();
int qian=0;
while(nextLine.contains("*"))
{
int index=nextLine.indexOf("*");
list.add(qian+index);
nextLine=nextLine.substring(index+1);
qian+=index+1;
}
return list;
}
}
题目6、区间移位
题目描述
数轴上有n个闭区间:D1,…,Dn。
其中区间Di用一对整数[ai, bi]来描述,满足ai < bi。
已知这些区间的长度之和至少有10000。
所以,通过适当的移动这些区间,你总可以使得他们的“并”覆盖[0, 10000]——也就是说[0, 10000]这个区间内的每一个点都落于至少一个区间内。
你希望找一个移动方法,使得位移差最大的那个区间的位移量最小。
具体来说,假设你将Di移动到[ai+ci, bi+ci]这个位置。你希望使得maxi{|ci|} 最小。
【输入格式】
输入的第一行包含一个整数n,表示区间的数量。
接下来有n行,每行2个整数ai, bi,以一个空格分开,表示区间[ai, bi]。
保证区间的长度之和至少是10000。
【输出格式】
输出一个数字,表示答案。如果答案是整数,只输出整数部分。如果答案不是整数,输出时四舍五入保留一位小数。
【样例输入】
2
10 5010
4980 9980
【样例输出】
20
【样例说明】
第一个区间往左移动10;第二个区间往右移动20。
【样例输入】
4
0 4000
3000 5000
5001 8000
7000 10000
【样例输出】
0.5
【样例说明】
第2个区间往右移0.5;第3个区间往左移0.5即可。
【数据规模与约定】
对于30%的评测用例,1 <= n <= 10;
对于100%的评测用例,1 <= n <= 10000,0 <= ai < bi <= 10000。
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
import java.io.*;
import java.util.*;
class S implements Comparable<S>
{
int l;
int r;
public S(int l,int r) {
this.l=l;
this.r=r;
}
@Override
public int compareTo(S o) {
// TODO Auto-generated method stub
if(this.r!=o.r)
return (int) (this.r-o.r);
else {
return (int) (this.l-o.l);
}
}
}
public class Main {
static int N=20000;
static S[]s=new S[10100];
static int []vis=new int [10100];
static int n;
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int now =0;
String str=br.readLine();
for(int i=0;i<str.length();i++) {
now=now*10+(int)(str.charAt(i)-'0');
}
n=now;
int sum=0;
for(int i=0;i<n;i++) {
now=0;
str=br.readLine();
int a = 0,b;
for(int j=0;j<str.length();j++) {
if(str.charAt(j)==' ') {
a=now;
now=0;
}
else {
now=now*10+(int)(str.charAt(j)-'0');
}
}
b=now;
sum+=b-a;
s[i]=new S(a*2,b*2);
}
Arrays.sort(s,0,n);
int l=0,r=N;
while(l<=r) {
int mid=(l+r)/2;
//System.out.println(mid);
if(check(mid)==true) {
r=mid-1;
}
else {
l=mid+1;
}
}
if(l%2==0) {
System.out.println(l/2);
}
else
System.out.println(((double)(l)*1.0)/2.0);
}
static boolean check(int x) {
int now=0;
for(int i=0;i<10100;i++) {
vis[i]=0;
}
while(true)
{
int flag=0;
int l=0,r=n;
while(l<=r) {
int mid=(l+r)/2;
if(s[mid].r+x>=now) {
r=mid-1;
}
else l=mid+1;
}
for(int i=l;i<n;i++) {
if(s[i].l<=x+now&&vis[i]==0) {
flag=1;
vis[i]=1;
if(now<=s[i].l+x) now+=s[i].r-s[i].l;
else now =s[i].r+x;
break;
}
}
if(now>=20000) return true;
if(flag==0) return false;
}
}
}