您的位置:首页 > 其它

【LQ系列】 BASIC-20~BASIC-25

2016-06-07 10:03 351 查看
蓝桥杯网站修好了,今天才关注到,补上上次没有发的BASIC-20和开始今天的五道题:

【BASIC-20】 基础练习 数的读法 

问题描述
  Tom教授正在给研究生讲授一门关于基因的课程,有一件事情让他颇为头疼:一条染色体上有成千上万个碱基对,它们从0开始编号,到几百万,几千万,甚至上亿。

  比如说,在对学生讲解第1234567009号位置上的碱基时,光看着数字是很难准确的念出来的。

  所以,他迫切地需要一个系统,然后当他输入12 3456 7009时,会给出相应的念法:

  十二亿三千四百五十六万七千零九

  用汉语拼音表示为

  shi er yi san qian si bai wu shi liu wan qi qian ling jiu

  这样他只需要照着念就可以了。

  你的任务是帮他设计这样一个系统:给定一个阿拉伯数字串,你帮他按照中文读写的规范转为汉语拼音字串,相邻的两个音节用一个空格符格开。

  注意必须严格按照规范,比如说“10010”读作“yi wan ling yi shi”而不是“yi wan ling shi”,“100000”读作“shi wan”而不是“yi shi wan”,“2000”读作“er qian”而不是“liang qian”。
输入格式
  有一个数字串,数值大小不超过2,000,000,000。
输出格式
  是一个由小写英文字母,逗号和空格组成的字符串,表示该数的英文读法。
样例输入
1234567009
样例输出
shi er yi san qian si bai wu shi liu wan qi qian ling jiu

(虽然这题测试用例通过了,但这题写的代码仍然有bug,例如:43000403,我注释在代码处了,纠结的地方就是当块内结构是 "0_0_"如何处理,因为我的思路是块内遇到一个零就将“判断是否输出ling标志”置false了,所以20403结果是"er qian ling si bai san",初步解决方案是每次判断是否将“输出ling标志”置false时判断(除块内最后一位外)块内后面还有没有0,如果有0,则保留true值,但感觉这样很麻烦,如果有简便方法的朋友请指导我下,谢谢~)

Code:

import java.util.Scanner ;

public class Main {

// 局部判断从ch[start]~ch[end]是否全为'0',如果是,则后面不必在判断了(以免输出多个"ling"),例如1000300,看1的时候要看到十万位和万位是不是0,是的话直接输出yi bai wan就好了,而不是yi bai ling ling wan
public static boolean isEnd( String str, int start, int end ) {
char[] ch = str.toCharArray() ;
boolean flag = true ; // 假定全为 '0'
for( int i = start; i <= end; i ++ ) {
if( ch[i] != '0' ) {
flag = false ;
break ;
}
}
return flag ;
}

// 将数字转换成拼音
public static String num_string( int num) {
switch( num ) {
case 0: return "" ;
case 1: return "yi" ;
case 2: return "er" ;
case 3: return "san" ;
case 4: return "si" ;
case 5: return "wu" ;
case 6: return "liu" ;
case 7: return "qi" ;
case 8: return "ba" ;
case 9: return "jiu" ;
}
return "ERROR" ;
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner( System.in ) ;
String str = sc.next() ;
char[] ch = str.toCharArray() ;
String result = "" ;
boolean flag_shi = true ; // 做个标志,区分输出 "..... shi yi wan" 还是" .... yi shi yi wan"。例如: 110000-->"shi yi wan"(而不是"yi shi yi wan") ; 8110000-->"ba bai yi shi yi wan"(而不是ba bai shi yi wan)
// 也就是说:当十万位 / 十位 前面有数字时且该位为 '1' 时输出"yi shi",否则只输出"shi"
int start = 0 ; // 还未考虑怎么读ch的起始判断位置
int end = ch.length - 1 ; // 还未考虑怎么读ch的终了判断位置
if( ch[0] == '-' ) { // 负号处理
result += "fu " ;
start ++ ;
}
while( start <= end ) {
/**
* 这里的思想是分块:
* 第一块:十亿位、亿位
* 第二块:千万位、百万位、十万位、万位
* 第三块:千位、百位、十位、个位
* 原因:除非块内全零,否则第一块后一定会输出"yi" 第二块后一定会输出"wan"
*/

/** 第一块 部分**/
if( end >= 9 ) { // 十亿位
if( num_string( (int) (ch[start] - '0') ).equals("yi") ) { // 如果最高位是'1',则是"shi ...."而不是"yi shi ...."
result += "shi" ;
start ++ ; // 不要把这句话加到上两行的if中 ( if(num_string( (int) (ch[start++] - '0') ).equals("yi")) ),这样每当判断后无论正确与否start已经++修改了,这里应该只有当进入if才start ++
}
else {
result += num_string( (int) (ch[start++] - '0') ) + " shi " ;
}
if( isEnd( str, start, start + 1 ) ) { // 查看十亿位后第一块后面是否全为0。是,则直接字符串+"yi", 否,则看该块内的下一位
result += " yi " ;
}
flag_shi = false ; // 判断十万位和十位特殊处理时用
}
if( end >= 8 ) { // 亿位
// if( isEnd( str, start, start ) ) { // 木有必要~
// result += "" ;
// start ++;
// }
// else {
result += num_string( (int) (ch[start ++] - '0') ) + " yi " ; // 亿位
// }
if( isEnd( str, start, ch.length-1 ) ) { // 第一块处理完毕,看第二块、第三块是否全位0。是,则直接结束,否,则看下一位
break ;
}
flag_shi = false ; // 判断十万位和十位时特殊处理用
}
/** 第二块部分**/
boolean flag_wan = true ; // 这里控制如果“万”部分有连续 ‘0’,只有第一个 0 会翻译成 "ling" ,例如:0010->ling yi shi
if( end >= 7 ) { // 千万位
if( ch[start] == '0' ) {
if( flag_wan ) { // 如果是第二块内第一次遇到 '0'
result += "ling " ;
flag_wan = false ; // 后面连续的 '0' 不再输出"ling"
}
start ++ ;
}
else {
result += num_string( (int) (ch[start ++] - '0') ) +" qian " ;
}
if( isEnd( str, start, start + 2 ) ) { // 判断第二块内后面是否全为0
result += "wan " ;
if( isEnd( str, start, str.length()-1 ) ) { // 如果第二块内全为0,但第三块还有数字,则输出一个"ling"再置false
result += "ling " ;
flag_wan = false ; // 让该块不再输出"ling"
}
}
flag_shi = false ; // 判断十万位和十位时用
}
if( end >= 6 ) { // 百万位
if( ch[start] == '0' ) {
if( flag_wan ) {
result += "ling " ;
flag_wan = false ;
}
start ++ ;
}
else {
result += num_string( (int) (ch[start ++] - '0') ) +" bai " ;
}
if( isEnd( str, start, start + 1 ) ) { // 检查第二块后面是否全为'0'
result += "wan " ;
if( isEnd( str, start, str.length()-1 ) ) { // 如果第二块内全为0,但第三块还有数字,则输出一个"ling"再置false
result += "ling " ;
flag_wan = false ; // 让该块不再输出"ling"
}
}
flag_shi = false ; // 判断十万位和十位时用
}
if( end >= 5 ) { // 十万位
if( ch[start] == '0' ) {
if( flag_wan ) {
result += "ling " ;
flag_wan = false ;
}
start ++ ;
}
else {
if( num_string( (int) (ch[start] - '0') ).equals("yi") && flag_shi) { // 如果十万位前面没有数字且该位为 '1' 则输出"shi"而不是"yi shi"
result += "shi " ;
start ++ ;
flag_shi = false ; // 判断十万位和十位时用
}
else {
result += nu
4000
m_string( (int) (ch[start ++] - '0') ) +" shi " ;
}
}
if( isEnd( str, start, start ) && flag_wan ) { // 查看万位是否为 0
result += "wan " ; // 这里有个 Bug!43000403
flag_wan = false ; // 让该块不再输出"ling"
}
}
if( end >= 4 ) { // 万
if( ch[start] == '0' ) {
if( flag_wan ) {
result += " ling " ;
flag_wan = false ;
}
start ++ ;
}
else {
result += num_string( (int) (ch[start ++] - '0') ) +" wan " ;
}
if( isEnd( str, start, ch.length-1 ) ) { // 第二块处理完毕,检查后面是否全为 '0'。 是,则终止,否,则看下一位
break ;
}
}

/** 第三块 部分**/
boolean flag_thousand = true ; // 这里控制如果“千百十个”部分有连续 ‘0’,只有第一个 0 会翻译成 "ling" ,例如:0023->ling er shi san
if( end >= 3 ) { // 千位
if( ch[start] == '0' ) {
if( flag_thousand ) { // 如果
result += "ling " ;
flag_thousand = false ;
}
start ++ ;
}
else {
result += num_string( (int) (ch[start ++] - '0') ) +" qian " ;
}
if( isEnd( str, start, ch.length-1 ) ) {
break ;
}
}
if( end >= 2 ) { // 白
if( ch[start] == '0' ) {
if( flag_thousand && flag_wan ) {
result += "ling " ;
flag_thousand = false ;
}
start ++ ;
}
else {
result += num_string( (int) (ch[start ++] - '0') ) +" bai " ;
}
if( isEnd( str, start, ch.length-1 ) ) {
break ;
}
}
if( end >= 1 ) { // 十
if( ch[start] == '0' ) {
if( flag_thousand ) {
result += "ling " ;
flag_thousand = false ;
}
start ++ ;
}
else {
if( num_string( (int) (ch[start] - '0') ).equals("yi") ) {
result += " shi" ;
start ++ ;
}
else {
result += num_string( (int) (ch[start ++] - '0') ) +" shi " ;
}
}
if( isEnd( str, start, ch.length-1 ) ) {
break ;
}
}
if( end >= 0 ) { // 个 (个位不需要"ling"判断)
result += num_string( (int) (ch[start ++] - '0') ) ;
}
System.out.println( result );
System.exit(0);
}
System.out.println( result );
}

}


【BASIC-21】 基础练习 Sine之舞 

问题描述
  最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数基本功。所以他准备和奶牛们做一个“Sine之舞”的游戏,寓教于乐,提高奶牛们的计算能力。

  不妨设

  An=sin(1–sin(2+sin(3–sin(4+...sin(n))...)

  Sn=(...(A1+n)A2+n-1)A3+...+2)An+1

  FJ想让奶牛们计算Sn的值,请你帮助FJ打印出Sn的完整表达式,以方便奶牛们做题。
输入格式
  仅有一个数:N<201。
输出格式
  请输出相应的表达式Sn,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。
样例输入
3
样例输出
((sin(1)+3)sin(1–sin(2))+2)sin(1–sin(2+sin(3)))+1

(这道题参考了http://blog.csdn.net/liangguojunainia/article/details/21484227 博文的代码和思路)

Code:

import java.util.Scanner ;

public class Main {

public static String An( int m, int n ) {
if( m == n )
return "sin(" + m + ")" ;
else
return "sin(" + m + ( m%2==0 ? "+" : "-" ) + An( m+1, n ) + ")" ;
}

public static String Sn( String str, int m, int n ) {
if( m > n )
return "" ;
else
return Sn( str, m+1, n ) + An( 1, n-m+1 ) + "+" + m ;
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner( System.in ) ;
int N = sc.nextInt() ;
String str = "" ;
str = Sn( str, 1, N ) ;
System.out.println( str );
}

}


 

【BASIC-22】 基础练习 FJ的字符串

问题描述
  FJ在沙盘上写了这样一些字符串:

  A1 = “A”

  A2 = “ABA”

  A3 = “ABACABA”

  A4 = “ABACABADABACABA”

  … …

  你能找出其中的规律并写所有的数列AN吗?
输入格式
  仅有一个数:N ≤ 26。
输出格式
  请输出相应的字符串AN,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。
样例输入
3
样例输出
ABACABA

(这道题参考了http://blog.csdn.net/hymanxq/article/details/25836453 博文的代码和思路,博主hymanxq采用递归的方法短小精悍,想了很久才领会,学习了~~)

Code:

import java.util.Scanner ;

public class Main {

private static String f( int n, String result ) {
if( n == 1 ) {
result += "A" ;
return result ;
}
result += f( n-1, result ) +(char) ( 'A'+n-1) + f( n-1, result ) ;
return result ;
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner( System.in ) ;
int N = sc.nextInt() ;
String result = new String() ;
result = f( N, result ) ;
System.out.println( result ) ;
}

}


【BASIC-23】 基础练习 芯片测试

问题描述
  有n(2≤n≤20)块芯片,有好有坏,已知好芯片比坏芯片多。

  每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时,能正确给出被测试芯片是好还是坏。而用坏芯片测试其他芯片时,会随机给出好或是坏的测试结果(即此结果与被测试芯片实际的好坏无关)。

  给出所有芯片的测试结果,问哪些芯片是好芯片。
输入格式
  输入数据第一行为一个整数n,表示芯片个数。

  第二行到第n+1行为n*n的一张表,每行n个数据。表中的每个数据为0或1,在这n行中的第i行第j列(1≤i, j≤n)的数据表示用第i块芯片测试第j块芯片时得到的测试结果,1表示好,0表示坏,i=j时一律为1(并不表示该芯片对本身的测试结果。芯片不能对本身进行测试)。
输出格式
  按从小到大的顺序输出所有好芯片的编号
样例输入
3

1 0 1

0 1 0

1 0 1
样例输出
1 3

Code:

import java.util.Scanner ;

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner( System.in ) ;
int n = sc.nextInt() ;
int[][] test = new int

;
int[] num_1 = new int
; // 统计n个芯片好的次数
for( int i = 0; i < num_1.length; i ++ )
num_1[i] = 0 ;
for( int i = 0; i < test.length; i ++ ) {
for( int j = 0; j < test[i].length; j ++ ) {
test[i][j] = sc.nextInt() ;
if( test[i][j] == 1 )
num_1[j] ++ ;
}
}
for( int i = 0; i < num_1.length; i ++ ) {
if( num_1[i] > n/2 )
System.out.print( (i+1) + " " ) ;
}
System.out.println();
}

}


【BASIC-24】 基础练习 龟兔赛跑预测 

问题描述
  话说这个世界上有各种各样的兔子和乌龟,但是研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔子和乌龟的赛跑。他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先t米或以上,它们就会停下来休息s秒。对于不同的兔子,t,s的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。

  然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找到了你——清华大学计算机系的高才生——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。
输入格式
  输入只有一行,包含用空格隔开的五个正整数v1,v2,t,s,l,其中(v1,v2<=100;t<=300;s<=10;l<=10000且为v1,v2的公倍数)
输出格式
  输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。

  第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。
样例输入
10 5 5 2 20
样例输出
D

4
样例输入
10 5 5 1 20
样例输出
R

3
样例输入
10 5 5 3 20
样例输出
T

4

Code:

import java.util.Scanner ;

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner( System.in ) ;
int v1 = sc.nextInt() ; // 兔子的速度
int v2 = sc.nextInt() ; // 乌龟的速度
int t = sc.nextInt() ; // 任意一秒当兔子发现领先 t 米或 t 米以上时
int s = sc.nextInt() ; // 兔子就会歇下来休息 s 秒
int l = sc.nextInt() ; // 赛道长度
int d1 = 0 ; // 兔子跑过的路程
int d2 = 0 ; // 乌龟跑过的路程
int i = 0, j = 0 ;
for( ; d1 < l && d2 < l; ) {
d1 += v1 ;
d2 += v2 ;
i ++ ;
if( d1 == l || d2 == l ) // 二者之一已经到达终点
break ;
if( d1 - d2 >= t )
for( int k = 0; k < s && d2 < l; j ++, k ++ ) { // 兔子歇 s 秒,且期间要判断乌龟到没到达终点
d2 += v2 ;
}
}
if( d1 == l && d2 == l ) // 平局
System.out.println( "D\n" + (i+j) ) ;
else if( d1 == l ) // 兔子胜
System.out.println( "R\n" + (i+j) ) ;
else if( d2 == l ) // 乌龟胜
System.out.println( "T\n" + (i+j) ) ;
}

}


【BASIC-25】 基础练习 回形取数

问题描述
  回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。
输入格式
  输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。
输出格式
  输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。
样例输入
3 3

1 2 3

4 5 6

7 8 9
样例输出
1 4 7 8 9 6 3 2 5
样例输入
3 2

1 2

3 4

5 6
样例输出
1 3 5 6 4 2

(这题自己写的代码超时了,所以参考了一些其他博文:
http://www.aichengxu.com/view/2460115:这篇博文代码也超时,但学习了另一种解题思路 http://www.cnblogs.com/watchfree/p/5307375.html:这篇博文代码测试通过
在这里小博有个疑问:同样的算法使用 C提交就可以通过,而且内存使用少很多,而使用Java就超时,这是因为语言编译执行的效率不同导致的吗?知道的朋友请求留个言哈~)

Code:(自己写的,代码可行但超时)

import java.util.Scanner ;

public class Main {

private static void display( int[][] A, boolean[][] flag, int m, int n ) {
int i = -1, j = 0 ;
int count = 0 ; // 走过数字的个数
while( count < n*m ) { // 如果还能向下的话继续循环
// 下
while( i+1<m && flag[i+1][j] ) {
System.out.print( A[++i][j] + " " ) ;
flag[i][j] = false ;
}
// 右
while( j+1<n && flag[i][j+1] ) {
System.out.print( A[i][++j] + " " ) ;
flag[i][j] = false ;
}
// 上
while( i-1 >= 0 && flag[i-1][j] ) {
System.out.print( A[--i][j] + " " ) ;
flag[i][j] = false ;
}
// 左
while( j-1 >= 0 && flag[i][j-1] ) {
System.out.print( A[i][--j] + " " ) ;
flag[i][j] = false ;
}
count ++ ;
}
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner( System.in ) ;
int m = sc.nextInt() ; // 行
int n = sc.nextInt() ; // 列
int[][] A = new int[m]
;
boolean[][]
b14a
flag = new boolean[m]
; // 标志数组,true:没访问过,false:已访问
for( int i = 0; i < m; i ++ ) {
for( int j = 0; j < n; j ++ ) {
A[i][j] = sc.nextInt() ;
flag[i][j] = true ;
}
}

display( A, flag, m, n ) ;
}

}


Code:(参考代码http://www.aichengxu.com/view/2460115,另一种思路,可行但也超时)

import java.util.Scanner ;

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input=new Scanner(System.in);
int m=input.nextInt() ; // m行
int n=input.nextInt(); // n 列
int[][] arr=new int[m]
;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
arr[i][j]=input.nextInt();
}
}
int i=0 ;
int j=0 ;
for (i = 0; i < (n + 1) / 2 && i < (m + 1) / 2; i++)
{
for (j = i; j < m - i; j++) // 下
System.out.print(arr[j][i]+" ");
for (j = i + 1; j < n - i; j++) // 右
System.out.print(arr[m - i - 1][j]+" ");
if (n - i - 1 > i)/*(当n为奇数时最后一次循环只有左一列的数据。)
前面每进一次循环都读了对称的两列数据,前面i-1次循环读了2i个数据(i从0开始)在这次判断之前又读了一列数据
所以判断有没有对称的右列数据只要判断n-2*i-1是否大于0(等价于n - i - 1 > i) */
for (j = m - i - 2; j >= i; j--) // 上
System.out.print( arr[j][n - i - 1]+" ");
if (m - i - 1 > i)
for (j = n - i - 2; j > i; j--) // 左
System.out.print( arr[i][j]+" ");
}
}

}

Code:(参考代码http://www.cnblogs.com/watchfree/p/5307375.html,算法同上,但用C编写的,通过)

#include <stdio.h>

int main()
{
int m,n,i,j;
int arr[210][210];
scanf("%d%d",&m,&n);

for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
scanf("%d",&arr[i][j]);

for(i = 0; i < (m+1)/2 && i < (n+1)/2; i++)
{
for(j = i; j < m-i; j++)
printf("%d ",arr[j][i]);
for(j = i+1; j < n-i; j++ )
printf("%d ",arr[m-i-1][j]);
if(n-i-1 > i)
{
for(j = m-i-2; j >= i; j--)
printf("%d ",arr[j][n-i-1]);
}
if (m-i-1 > i)
{
for(j = n-i-2; j > i; j--)
printf("%d ",arr[i][j]);
}
}

return 0;
}

叨叨叨:

        题目越往后感觉思路越是跟不上,总是需要参考其他网站的代码,等有时间了我会修改所有【LQ系列】博文,适当配上文字思路,这样有助于众多访友们的理解和自己对题目的剖析。

这篇博文虽是原创,但也参考了很多其他博友的原创博文,如果转载请附上该博文中参考的原创博文链接,谢谢~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: