2011年 “蓝桥杯”选拔赛 java 本科
1. 代码填空 (满分3分)
圆周率
我国古代数学家对圆周率方面的研究工作,成绩是突出的。三国时期的刘徽、南北朝时期的祖冲之都在这个领域取得过辉煌战绩。
有了计算机,圆周率的计算变得十分容易了。如今,人们创造了上百种方法求π的值。其中比较常用且易于编程的是无穷级数法。
π/4 = 1 – 1/3 + 1/5 – 1/7 + 1/9 - …
是初学者特别喜欢的一个级数形式,但其缺点是收敛太慢。
π/2 = 1 + 1/3 +1/3*2/5 + 1/3*2/5*3/7 + 1/3*2/5*3/7*4/9 + …
是收敛很快的一个级数方法。下面的代码演示了用这种方法计算π值。请填写缺失的代码部分。把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
package LanQiaoBei;
public class Java2011_1 {
public static void main(String[] args) {
double x = 1;
double y = 1;
int a = 1;
int b = 3;
while(y>1e-15)
{
y = y*a/b;
x += y;
a++;
b += 2;
}
System.out.println(x*2);
}
}
2. 代码填空 (满分4分)
孪生素数
所谓孪生素数指的就是间隔为 2 的相邻素数,它们之间的距离已经近得不能再近了,就象孪生兄弟一样。最小的孪生素数是 (3, 5),在 100 以内的孪生素数还有 (5, 7), (11, 13), (17, 19), (29, 31), (41, 43), (59, 61) 和 (71, 73),总计有 8 组。但是随着数字的增大,孪生素数的分布变得越来越稀疏,寻找孪生素数也变得越来越困难。那么会不会在超过某个界限之后就再也不存在孪生素数了呢?
孪生素数有无穷多对!这个猜想被称为孪生素数猜想,至今没有被严格证明。但借助于计算机我们确实可以找到任意大数范围内的所有孪生素数对。
下面的代码求出了正整数n以内(不含n)的所有孪生素数对的个数。比如,当n=100的时候,该方法返回8。试补全缺少的代码。把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
package LanQiaoBei;
public class Java2011_2 {
public static void main(String[] args) {
for(int i=0; i<=100; i++) {
System.out.println(i + " " + twinPrimeNum(i));
}
}
public static boolean isPrime(int x)
{
for(int i=2; i<=x/2; i++)
{
if(x%i==0) return false;//11111111111
}
return true;
}
public static int twinPrimeNum(int n)
{
int sum = 0;
for(int i=2; i<n; i++)
{
if(isPrime(i) && isPrime(i+2)) sum++;//2222222222222
}
return sum;
}
}
3. 代码填空 (满分5分)
反转串
我们把“cba”称为“abc”的反转串。
求一个串的反转串的方法很多。下面就是其中的一种方法,代码十分简洁(甚至有些神秘),请聪明的你通过给出的一点点线索补充缺少的代码。把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
package LanQiaoBei;
public class Java2011_3 {
public static void main(String[] args) {
System.out.println(reverseString("123456"));
}
public static String reverseString(String x)
{
if(x==null || x.length()<2) return x;
return reverseString(x.substring(1, x.length())) + x.charAt(0);//111111111111
}
}
4. 代码填空(满分7分)
最近距离
已知平面上的若干点的位置,存入一个List中。现在需要计算所有这些点中,距离最近的两个点间的最小距离。请补全缺失的代码。把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
package LanQiaoBei;
import java.util.LinkedList;
import java.util.List;
public class Java2011_4{
public static void main(String[] args) {
List<MyPoint> list = new LinkedList<MyPoint>();
list.add(new MyPoint(1, 2));
list.add(new MyPoint(2, 1));
list.add(new MyPoint(5, 8));
list.add(new MyPoint(5, 9));
list.add(new MyPoint(9, 6));
list.add(new MyPoint(11, 13));
double result = MyPoint.getMinDistance(list);
System.out.println(result);
}
static class MyPoint
{
private double x; // 横坐标
private double y; // 纵坐标
public MyPoint(double x, double y)
{
this.x = x;
this.y = y;
}
public static double distance(MyPoint p1, MyPoint p2)
{
double dx = p1.x - p2.x;
double dy = p1.y - p2.y;
return Math.sqrt(dx*dx + dy*dy);
}
/*
lst中含有若干个点的坐标
返回其中距离最小的点的距离
*/
public static double getMinDistance(List<MyPoint> lst)
{
if(lst==null || lst.size()<2) return Double.MAX_VALUE;
double r = Double.MAX_VALUE;
MyPoint p0 = lst.remove(0);
for(int i=0; i<lst.size(); i++)
{
MyPoint p = lst.get(i);
double d = MyPoint.distance(p0,p);
if(d<r) r=d;//11111111111111111111
}
double d2 = getMinDistance(lst);//222222222222222222
return d2 < r ? d2 : r;
}
}
}
5. 代码填空 (满分9分)
基因牛
张教授采用基因干预技术成功培养出一头母牛,三年后,这头母牛每年会生出1头母牛, 生出来的母牛三年后,又可以每年生出一头母牛。如此循环下去,请问张教授n年后有多少头母牛?
以下程序模拟了这个过程,请填写缺失的代码。把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
package LanQiaoBei;
import java.util.ArrayList;
import java.util.List;
public class Java2011_5 {
public static void main(String[] args) {
}
}
class Cow
{
private int age;
public Cow afterYear()
{
age++;
return age > 2 ? new Cow() : null;//1111111111111111
}
public static void showTotalCowNum(int n)
{
List<Cow> list = new ArrayList<Cow>();
list.add(new Cow());
for (int i = 0; i < n; i++)
{
int cowCount = list.size();
for (int j = 0; j < cowCount; j++)
{
Cow cow = list.get(j).afterYear();
if (cow != null)
{
cow = new Cow(); //222222222222222222
list.add(cow);
}
}
}
System.out.println(n + "年后,共有:" + list.size());
}
}
6. 代码填空 (满分19分)
迷宫问题
对于走迷宫,人们提出过很多计算机上的解法。深度优先搜索、广度优先搜索是使用最广的方法。生活中,人们更愿意使用“紧贴墙壁,靠右行走”的简单规则。
下面的代码则采用了另一种不同的解法。它把走迷宫的过程比做“染色过程”。假设入口点被染为红色,它的颜色会“传染”给与它相邻的可走的单元。这个过程不断进行下去,如果最终出口点被染色,则迷宫有解。
仔细分析代码中的逻辑,填充缺少的部分。把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
package LanQiaoBei;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Maze
{
class Cell
{
private int row;
private int col;
private Cell from;
public Cell(int row, int col, Cell from)
{
this.row = row;
this.col = col;
this.from = from;
}
}
char[][] maze =
{{'#','#','#','#','B','#','#','#','#','#','#','#'},
{'#','#','#','#','.','.','.','.','#','#','#','#'},
{'#','#','#','#','.','#','#','#','#','.','.','#'},
{'#','.','.','.','.','#','#','#','#','#','.','#'},
{'#','.','#','#','#','#','#','.','#','#','.','#'},
{'#','.','#','#','#','#','#','.','#','#','.','#'},
{'#','.','#','#','.','.','.','.','.','.','.','#'},
{'#','.','#','#','.','#','#','#','.','#','.','#'},
{'#','.','.','.','.','#','#','#','.','#','.','#'},
{'#','#','.','#','.','#','#','#','.','#','.','A'},
{'#','#','.','#','#','#','.','.','.','#','#','#'},
{'#','#','#','#','#','#','#','#','#','#','#','#'}};
public void show()
{
for(int i=0; i<maze.length; i++)
{
for(int j=0; j<maze[i].length; j++)
System.out.print(" " + maze[i][j]);
System.out.println();
}
}
//把与from集合中相邻的可染色节点染色,被染色节点记入 dest
//一旦发现出口将被染色,则返回当前的“传播源”节点
public Cell colorCell(Set<Cell> from, Set<Cell> dest)
{
Iterator<Cell> it = from.iterator();
while(it.hasNext())
{
Cell a = it.next();
Cell[] c = new Cell[4];
c[0] = new Cell(a.row-1, a.col, a);
c[1] = new Cell(a.row, a.col-1, a);
c[2] = new Cell(a.row+1, a.col, a);
c[3] = new Cell(a.row, a.col+1, a);//1111111111111111111111
for(int i=0; i<4; i++)
{
if(c[i].row < 0 || c[i].row >= maze.length) continue;
if(c[i].col < 0 || c[i].col >= maze[0].length) continue;
char x = maze[c[i].row][c[i].col];
if(x=='B') return a;
if(x=='.')
{
maze[c[i].row][c[i].col] = '?';
dest.add(c[i]);//2222222222222222222
}
}
}
return null;
}
public void resolve()
{
Set<Cell> set = new HashSet<Cell>();
set.add(new Cell(9,11,null));
for(;;)
{
Set<Cell> set1 = new HashSet<Cell>();
Cell a = colorCell(set, set1);
if(a!=null)
{
System.out.println("找到解!");
while(a!=null)
{
maze[a.row][a.col] = '+';
a = a.from;//33333333333333333333333333
}
break;
}
if(set1.isEmpty())
{
System.out.println("无解!");
break;
}
set = set1;
}
}
public static void main(String[] args)
{
Maze m = new Maze();
m.show();
m.resolve();
m.show();
}
}
7. 程序设计 (满分12分)
在中文Windows环境下,控制台窗口中也可以用特殊符号拼出漂亮的表格来。
比如:
┌─┬─┐
│ │ │
├─┼─┤
│ │ │
└─┴─┘
其实,它是由如下的符号拼接的:
左上 = ┌
上 = ┬
右上 = ┐
左 = ├
中心 = ┼
右 = ┤
左下= └
下 = ┴
右下 = ┘
垂直 = │
水平 = ─
本题目要求编写一个程序,根据用户输入的行、列数画出相应的表格来。
例如用户输入:
3 2
则程序输出:
┌─┬─┐
│ │ │
├─┼─┤
│ │ │
├─┼─┤
│ │ │
└─┴─┘
用户输入:
2 3
则程序输出:
┌─┬─┬─┐
│ │ │ │
├─┼─┼─┤
│ │ │ │
└─┴─┴─┘
要求考生把所有类写在一个文件中。调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。相关的工程文件不要拷入。请不要使用package语句。
另外,源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。
package LanQiaoBei;
import java.util.Scanner;
public class Java2011_7 {
private static String leftUp = "┌";
private static String up = "┬";
private static String rightUp = "┐";
private static String left = "├";
private static String center = "┼";
private static String right = "┤";
private static String leftDown = "└";
private static String down = "┴";
private static String rightDown = "┘";
private static String vertical = "│";
private static String hori = "─";
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int row, col;
while(sc.hasNext()) {
row = sc.nextInt();
col = sc.nextInt();
draw(row, col);
}
}
private static void draw(int row, int col) {
//第一行
System.out.print(leftUp);
for(int i=1; i<col; i++) {
System.out.print(hori + up);
}
System.out.println(hori + rightUp);
//2-(n-1)行
for(int i=1; i<row; i++) {
for(int j=1; j<=col+1; j++) {
if(j != col+1) {
System.out.print(vertical + " ");
}else {
System.out.print(vertical);
}
}
System.out.println();
for(int j=1; j<=col+1; j++) {
if(j == 1) {
System.out.print(left);
} else if(j != col+1) {
System.out.print(hori + center);
} else {
System.out.print(hori + right);
}
}
System.out.println();
}
//第n行
for(int j=1; j<=col+1; j++) {
if(j != col+1) {
System.out.print(vertical + " ");
}else {
System.out.print(vertical);
}
}
System.out.println();
for(int i=1; i<=col+1; i++) {
if(i==1) {
System.out.print(leftDown + hori);
} else if(i!=col+1) {
System.out.print(down + hori);
} else {
System.out.print(rightDown);
}
}
System.out.println();
}
}
8. 程序设计 (满分17分)
某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔。如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?
如果有多种可能,则输出所有可能的情况。
我们规定:用户输入的第一行是:有错的总金额。
接下来是一个整数n,表示下面将要输入的明细账目的条数。
再接下来是n行整数,分别表示每笔账目的金额。
要求程序输出:所有可能漏掉的金额组合。每个情况1行。金额按照从小到大排列,中间用空格分开。
比如:
用户输入:
6
5
3
2
4
3
1
表明:有错的总金额是6;明细共有5笔。
此时,程序应该输出:
1 3 3
1 2 4
3 4
为了方便,不妨假设所有的金额都是整数;每笔金额不超过1000,金额的明细条数不超过100。
要求考生把所有类写在一个文件中。调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。相关的工程文件不要拷入。请不要使用package语句。
另外,源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。
package LanQiaoBei;
import java.util.Arrays;
import java.util.Scanner;
public class Java2011_8 {
private static int caseMoneys[];
private static boolean[] tag;
private static String str = "";
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int money = sc.nextInt();
int n = sc.nextInt();
caseMoneys = new int[n];
tag = new boolean[n];
int sum = 0;
for(int i=0; i<n; i++) {
caseMoneys[i] = sc.nextInt();
sum += caseMoneys[i];
}
Arrays.sort(caseMoneys);
search(0, 0, sum-money);
}
private static void search(int cur, int tempMoney, int money) {
if(tempMoney==money) {
show(tag, money);
} else {
for(int i=cur; i<caseMoneys.length; i++) {
if(tag[i]==false && tempMoney+caseMoneys[i]<=money) {
tag[i] = true;
search(i+1, tempMoney+caseMoneys[i], money);
tag[i] = false;
} else {
break;
}
}
}
}
private static void show(boolean[] tag, int finalMoney) {
int money = 0;
StringBuffer sb = new StringBuffer();
for(int i=0; i<tag.length; i++) {
if(tag[i] == true) {
money += caseMoneys[i];
if(money != finalMoney) {
sb.append(caseMoneys[i] + " ");
} else {
sb.append(caseMoneys[i]);
}
}
}
if(!str.equals(sb.toString())){
System.out.println(sb.toString());
str = sb.toString();
}
}
}
9. 程序设计(满分24分)
一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下:
1.首先按行填入密钥串。
2.紧接其后,按字母序按行填入不在密钥串中的字母。
3.由于方阵中只有25个位置,最后剩下的那个字母则不需变换。
如果密钥为youandme,则该方阵如下:
y o u a n
d m e b c
f g h i j
k l p q r
s t v w x
在加密一对字母时,如am,在方阵中找到以这两个字母为顶点的矩形(红色字体):
y o u a n
d m e b c
f g h i j
k l p q r
s t v w x
这对字母的加密字母为该矩形的另一对顶点,如本例中为ob。
请设计程序,使用上述方法对输入串进行加密,并输出加密后的串。
另外有如下规定:
1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中;
2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;
3、如果一对字母中有一个字母不在正方形中,则不变换,直接放入加密串中;
4、如果字母对出现在方阵中的同一行或同一列,如df或hi,则只需简单对调这两个字母,即变换为fd或ih;
5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为am,则该矩形的另一对顶点字母中,与a同行的字母应在前面,在上例中应是ob;同样若待变换的字母对为ta,则变换后的字母对应为wo;
6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。
解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。
要求输入形式如下:
从控制台输入两行字符串,第一行为密钥单词(长度小于等于25),第二行为待加密字符串(长度小于等于50),两行字符串末尾都有一个回车换行符,并且两行字符串均为小写字母,不含其它字符。
在标准输出上输出加密后的字符串。
例如,若输入:
youandme
welcometohangzhou
则表示输入的密钥单词为youandme,形成的正方形如上所示;待加密字符串为welcometohangzhou。在正方形中可以找到以第一对字母we为顶点的矩形,对应另一对顶点字母为vb,因此加密后为vb,同理可找到与字母对lc,et,oh,ho对应的顶点字母对。而字母对om位于上述正方形中的同一列,所以直接以颠倒这两个字母来加密,即为mo,字母对an同理。字母对gz中的z不在上述正方形中,因此原样放到加密串中。最后剩一个字母u也原样输出。
因此输出的结果为:
vbrmmomvugnagzguu
要求考生把所有类写在一个文件中。调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。相关的工程文件不要拷入。请不要使用package语句。
另外,源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。
package LanQiaoBei;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Java2011_9 {
private static final int N = 6;
private static char[][] map = new char[N][N];
private static Map<Character, Node> mapSearch = new HashMap<Character, Node>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.next();
String str2 = sc.next();
initMap(str);
initSearchMap();
sovle(str2);
}
private static void sovle(String str) {
StringBuffer sb = new StringBuffer();
int len = str.length();
char a, b;
Node nodea, nodeb;
for(int i=1; i<len; i+=2) {
a = str.charAt(i-1);
b = str.charAt(i);
nodea = mapSearch.get(a);
nodeb = mapSearch.get(b);
if(a == b) {
sb.append(a).append(b);
} else if(nodea==null || nodeb==null) {
sb.append(a).append(b);
} else if(nodea.col==nodeb.col || nodea.row==nodeb.row) {
sb.append(b).append(a);
} else {
sb.append(map[nodea.row][nodeb.col]).append(map[nodeb.row][nodea.col]);
}
}
if(sb.length() != len) {
sb.append(str.charAt(len-1));
}
System.out.println(sb.toString());
}
private static void initSearchMap() {
for(int i=0; i<N; i++) {
for(int j=0; j<N; j++) {
mapSearch.put(map[i][j], new Java2011_9().new Node(i, j));
}
}
}
private static void initMap(String str) {
boolean[] tag = new boolean[26];
char ch = '0';
int len = str.length();
int count = 0;
int a = 'a';
for(int i=1; i<N; i++) {
for(int j=1; j<N; j++) {
if(count < len) {
ch = str.charAt(count ++);
tag[ch-'a'] = true;
map[i][j] = ch;
} else {
while(tag[a-'a'] == true) {
a++;
}
map[i][j] = (char)a;
tag[a-'a'] = true;
a++;
}
}
}
}
class Node {
int row;
int col;
public Node(int row, int col) {
this.row = row;
this.col = col;
}
}
}