第3章在线编程题参考答案 3.1第1章绪论 1. POJ1004——财务管理问题 时间限制: 1000ms; 空间限制: 10000KB。 问题描述: 拉里今年毕业,终于找到了工作。他赚了很多钱,但似乎还没有足够的钱,拉里决定抓住金融投资机会解决他的财务问题。拉里有自己的银行账户报表,他想看看自己有多少钱。请编写一个程序帮助拉里从过去12个月的每一月中取出他的期末账户余额并计算他的平均账户余额。 输入格式: 输入为12行,每行包含特定月份的银行账户的期末余额,每个数字都是正数并到便士为止,不包括美元符号。 输出格式: 输出一个数字,即12个月的期末账户余额的平均值(平均值),它将四舍五入到最近的便士,紧接着是美元符号,然后是行尾。在输出中不会有其他空格或字符。 输入样例: 100.00 489.12 12454.12 1234.10 823.05 109.20 5.27 1542.25 839.18 83.99 1295.01 1.75 输出样例: $1581.42 解: 读取每个月份的期末账户余额temp,累加到sum中,输出sum/12的结果。对应的AC程序如下: import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner fin=new Scanner(System.in); double temp=0.00,sum=0.00; int iMax=12; while(iMax-->0) {temp=fin.nextDouble(); sum += temp; } System.out.printf("$%.2f\n",sum/12); } } 上述程序的执行时间为188ms,执行空间为3228KB。 第3章在线编程题参考答 案 数据结构教程(Java语言描述)学习与上机实验指导 2. HDU2012——素数判定问题 时间限制: 2000ms; 空间限制: 65536KB。 问题描述: 对于表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括x、y,-39≤xy) {int temp = x; x = y; y = temp; } for(int i = x; i <= y; i++) {num=i*i+i+41; for(int j = 2; j <= Math.sqrt(num); j++)//素数判断 {if(num % j == 0) flag = false; } } if(flag == true) System.out.println("OK"); else System.out.println("Sorry"); flag = true; } } } } 上述程序的执行时间为296ms,执行空间为9312KB。 提示: 在本书所有在线编程题中,POJ题目的限制时间和空间是针对C/C++程序的,通常Java程序的时间和空间是其两倍,HDU题目的限制时间和空间就是针对Java程序的。 3.2第2章线性表 1. HDU2019——数列有序问题 时间限制: 2000ms; 空间限制: 65536KB。 问题描述: 有n(n≤100)个整数,已经按照从小到大的顺序排列好,现在另外给一个整数m,请将该数插入序列中,并使新的序列仍然有序。 输入格式: 输入数据包含多个测试实例,每组数据由两行组成,第一行是n和m,第二行是已经有序的n个数的数列。n和m同时为0表示输入数据的结束,本行不做处理。 输出格式: 对于每个测试实例,输出插入新的元素后的数列。 输入样例: 3 3 1 2 4 0 0 输出样例: 1 2 3 4 解: 对于每个测试实例,n个有序整数采用顺序表存放,为了简单,这里顺序表直接用数组a表示。先查找插入m的位置i,将a[i..n-1]的所有元素均后移一个位置,置a[i]=m。对应的AC程序如下: import java.util.*; public class Main {public static void main(String args[]) {Scanner cin=new Scanner(System.in); while(cin.hasNext())   //读取每个测试实例 {int n=cin.nextInt();   //读取n int m=cin.nextInt();   //读取m if(n==0 && m==0)   //结束 break; else {int a[]=new int[105];   //最多100个整数 for(int i=0;ia[n-1])   //m最大,插入末尾 a[n]=m; else {for(int i=0;ij;i--)   //将a[i..n-1]后移一个位置 a[i]=a[i-1]; a[i]=m;   //插入a[i] break;   //退出查找 } } } for(int i=0;i<=n;i++)   //输出新序列 if(i==0) System.out.print(a[i]); else System.out.print(" "+a[i]); } System.out.println(); } } } 上述程序的执行时间为265ms,空间为9412KB。 2. HDU1443——Joseph(约瑟夫)问题 时间限制: 2000ms; 空间限制: 65536KB。 问题描述: Joseph问题是众所周知的。有n个人,编号为1,2,…,n,站在一个圆圈中,每隔m个人就杀一个人,最后仅剩下一个人。Joseph很聪明,可以选择最后一个人的位置,从而挽救他的生命。例如,当n=6且m=5时,按顺序出列的人员是5,4,6,2,3,1,那么1会活下来。 假设在圈子里前面恰好有k个好人,后面恰好有k个坏人,则必须确定所有坏人都在第一个好人前面被杀的最小m。 输入格式: 输入文件中包含若干行,每行一个k,最后一行为0,可以假设0k;cnt--)   //检查是否满足要求 {p=(p+m-1) % cnt;   //被杀掉的人的位置 if(p= 10)   //有进位 {c[i+1] += c[i]/10; c[i] %= 10; } String ans=""; for(i=c.length-1;i>=0; i--)   //删除前导零 if(c[i]!=0) break; for(;i>=0; i--) ans += c[i]; return ans; } public static void main(String[] args) {Scanner cin = new Scanner(System.in); String s1,s2; s1=cin.nextLine(); s2=cin.nextLine(); String s3=mult(s1,s2); System.out.println(s3); } } 上述程序的执行时间为1266ms,空间是2964KB。实际上,本题目可以直接使用Java的长整数类型来实现,对应的AC程序如下: import java.math.BigInteger; import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner cin = new Scanner(System.in); BigInteger a = cin.nextBigInteger(); BigInteger b = cin.nextBigInteger(); a = a.multiply(b); System.out.println(a); } } 上述程序的执行时间为1375ms,空间是3036KB。 说明: 尽管在线性表部分中讨论了多种存储结构,但在实际在线编程中,为了简单和提高效率往往直接采用数组代替顺序表,相反链表较少使用,其原因之一是在这类题目中都确定了数据量的大小,适合采用顺序结构,另外链表由于结点地址不连续,内存寻址空间较大,导致存取效率较低。 3.3第3章栈和队列 1. HDU1237——简单计算器 时间限制: 2000ms; 空间限制: 65536KB。 问题描述: 读入一个只包含+、-、*、/的非负整数计算的表达式,计算该表达式的值。 输入格式: 测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔; 没有非法表达式; 当一行中只有0时输入结束,相应的结果不要输出。 输出格式: 对每个测试用例输出一行,即该表达式的值,精确到小数点后两位。 输入样例: 1 + 2 4 + 2 * 5 - 7 / 11 0 输出样例: 3.00 13.36 解: 与《教程》中3.1.7节“用栈求解简单表达式求值问题”的原理相同,由于这里不包括括号,所以更简单一些,将求表达式值的两个步骤合并起来。 设计运算数栈为opand,运算符栈为oper。先将输入行str拆分为strs字符串数组,用i遍历strs: (1) 若strs[i]为“*”或者“/”,为最高优先级,将oper栈顶为“*”或者“/”的运算符先计算,再将strs[i]进oper栈。 (2) 若strs[i]为“+”或者“-”,为最低优先级,将oper栈中所有的运算符先计算,再将strs[i]进oper栈。 (3) 其他为运算数,将其进opand栈。 最后输出opand的栈顶数值。 对应的AC程序如下: import java.util.*; import java.util.Scanner; public class Main {static Stack opand=new Stack();   //运算数栈 static Stack oper=new Stack();   //运算符栈 public static boolean Same(String s1,String s2)   //比较两个字符串值是否相同 { return s1.compareTo(s2)==0; } public static void comp(String op)   //用于一个运算符的计算 {double a=opand.pop();   //从opand中出栈两个数a和b double b=opand.pop(); double c=0.0; if(Same(op,"+"))   //op为“+” c=b+a; else if(Same(op,"-"))   //op为“-” c=b-a; else if(Same(op,"*"))   //op为“*” c=b*a; else if(Same(op,"/"))   //op为“/” c=b/a; opand.push(c);   //结果进opand栈 } public static void main(String[] args) {Scanner fin = new Scanner(System.in); while(fin.hasNext()) {String str=fin.nextLine();   //接收输入的字符串 if(str.compareTo("0")==0)   //若是只输入0,则结束 break; opand.clear(); oper.clear(); String[] strs=str.split(" ");   //根据题目要求分割字符串 String op; double a,b,c; int i=0; while(i