蓝桥杯网站修好了,今天才关注到,补上上次没有发的BASIC-20和开始今天的五道题:
【BASIC-20】 基础练习 数的读法
比如说,在对学生讲解第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”。
(虽然这题测试用例通过了,但这题写的代码仍然有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 += num_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之舞
不妨设
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的完整表达式,以方便奶牛们做题。
(这道题参考了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的字符串
A1 = “A”
A2 = “ABA”
A3 = “ABACABA”
A4 = “ABACABADABACABA”
… …
你能找出其中的规律并写所有的数列AN吗?
(这道题参考了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+1行为n*n的一张表,每行n个数据。表中的每个数据为0或1,在这n行中的第i行第j列(1≤i, j≤n)的数据表示用第i块芯片测试第j块芯片时得到的测试结果,1表示好,0表示坏,i=j时一律为1(并不表示该芯片对本身的测试结果。芯片不能对本身进行测试)。
1 0 1
0 1 0
1 0 1
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[n][n] ;
int[] num_1 = new int[n] ; // 统计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】 基础练习 龟兔赛跑预测
然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找到了你——清华大学计算机系的高才生——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。
第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。
4
3
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】 基础练习 回形取数
1 2 3
4 5 6
7 8 9
1 2
3 4
5 6
(这题自己写的代码超时了,所以参考了一些其他博文:
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][n] ;
boolean[][] flag = new boolean[m][n] ; // 标志数组,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][n] ;
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系列】博文,适当配上文字思路,这样有助于众多访友们的理解和自己对题目的剖析。
这篇博文虽是原创,但也参考了很多其他博友的原创博文,如果转载请附上该博文中参考的原创博文链接,谢谢~