PTA题目集1~3的总结
一、前言
在新学期中我们初步学习了JAVA这门新的计算机语言,相较于之前学习的c语言,数据结构,JAVA在算法的运用上几乎相同,但又有许多差异。JAVA语言最大的特点是要构造类,并通过用类来创建对象以及用对象的思维来解决问题。而我通过这三次PTA大作业,我学习了很多JAVA的知识点、语法以及方法。我也慢慢地理解了类和对象的语义和思维方法,并且在这三次作业中,我也尽量地用类和对象的思维方法来做题,以便帮助自己更好地在实践中灵活运用。
在前三次PTA的作业中,涉及到的知识点包括从最基础的命名变量到对象和类,选择结构,循环结构,字符和字符串以及方法的定义与调用,对象数组的创建及使用,以及第三次作业当中需要用到的关于点、线、三角形计算的各种数学函数。这三次的大作业,第一次的题量较多,后面两次的较少,我都能在规定时间内做完,但最后一次作业没有做全对。难度循序渐进,第一次较为简单,第二次适中,第三次较难,以至于没有拿到满分。特别是第三次的作业,虽然只有三道题,但是每道题的难度都很大,且题目之间层层递进,后面的题都建立在上道题的基础上而又衍生出新的问题。对于初步学习Java的我来说很具有挑战性。
二、设计与总结
1.题目集二—7-2 串口字符解析
(1)题目分析:RS232是串口常用的通信协议,在异步通信模式下,串口可以一次发送5~8位数据,收发双方之间没有数据发送时线路维持高电平,相当于接收方持续收到数据“1”(称为空闲位),发送方有数据发送时,会在有效数据(5~8位,具体位数由通信双方提前设置)前加上1位起始位“0”,在有效数据之后加上1位可选的奇偶校验位和1位结束位“1”。请编写程序,模拟串口接收处理程序,注:假定有效数据是8位,奇偶校验位采用奇校验。
输入格式:
由0、1组成的二进制数据流。例如:11110111010111111001001101111111011111111101111
输出格式:
过滤掉空闲、起始、结束以及奇偶校验位之后的数据,数据之前加上序号和英文冒号。
如有多个数据,每个数据单独一行显示。
若数据不足11位或者输入数据全1没有起始位,则输出"null data",
若某个数据的结束符不为1,则输出“validate error”。
若某个数据奇偶校验错误,则输出“parity check error”。
若数据结束符和奇偶校验均不合格,输出“validate error”。
如:11011或11111111111111111。
例如:
1:11101011
2:01001101
3:validate error
源代码如下:
查看代码 import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
String str=in.next();
if(str.length()<11) {
System.out.print("null data");
return;
}
if(str.matches("^[1]*$")) {
System.out.print("null data");
return;
}
int start=0,i=0,num=1,sum=0;
boolean parity = false,validate=false;
for(start=0;start<str.length()-10;start++){
if(str.charAt(start)=='0') {
System.out.print(num+":");
num++;
if(str.charAt(start+10)=='0'){
validate=false;
}
else{
validate=true;
sum=0;
for(i=start+1;i<start+9;i++){
if(str.charAt(i)=='1') {
sum++;
}
}
if(sum%2==0){
if(str.charAt(start+9)=='1'){
parity=true;
}
else{
parity=false;
}
}
else{
if(str.charAt(start+9)=='0'){
parity=true;
}
else{
parity=false;
}
}
}
if(validate==true){
if(parity==true){
for(i=start+1;i<start+9;i++){
System.out.print(str.charAt(i));
}
System.out.print("\n");
}
else{
System.out.println("parity check error");
}
}
else{
System.out.println("validate error");
}
start=start+10;
}
}
}
}
该题目是对串口字符解析,整体题目结构不复杂,故也不需要创建多个类进行解答,只需使用Main类。首先得对该题目进行详细的分析,经过查询相关奇偶效验性的含义,明白奇偶效验是判断“1”的个数为奇数还是偶数,并是采用的是奇效验,判定的数据段为有效数据和其后一位计算判定,再运用for循环语句,if-else语句,变量标识符,解答该题目。
(2)踩坑心得:
这题需要注意的是,题目中的奇偶校验是用前面的合法的数据相加再加上数据倒数第二位的奇偶校验来判断数据是否合格并输出,否则样例6的测试点过不了。
(3)改进建议:
对输入的数据流进行过滤输出,首先就需要判断数据流的长度是否满足11位,再进行调用judge方法进行判断,判断是否存在有效数据(有效数据前一位为0),若judge方法返回 true 则说明存在的有效数据,进行下一步判断,之后设置for循环,在for循环里面用if-else语句根据奇校验位数以及结束符判断是否正确分类输出。这样写可以使代码更简洁一些,可读性更高。
2.题目集三—7-1 点线形系列1-计算两点之间的距离
(1)题目分析:输入连个点的坐标,计算两点之间的距离
输入格式:
4个double类型的实数,两个点的x,y坐标,依次是x1、y1、x2、y2,两个点的坐标之间以空格分隔,每个点的x,y坐标以英文“,”分隔。例如:0,0 1,1或0.1,-0.3 +3.5,15.6。
若输入格式非法,输出"Wrong Format"。
若输入格式合法但坐标点的数量超过两个,输出“wrong number of points”。
输出格式:
计算所得的两点之间的距离。例如:1.4142135623730951
源代码如下:
查看代码 import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String input = in.nextLine();
String point[] = input.split(" ");
String num[] = null;
for(String i:point) {
num = i.split(",");
for(String j:num) {
if(!j.matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$")) {
System.out.print("Wrong Format");
System.exit(0);
}
}
}
if(point.length!=2)
{
System.out.print("wrong number of points");
System.exit(0);
}
num = point[0].split(",");
double a = Double.valueOf(num[0]);
double b = Double.valueOf(num[1]);
num = point[1].split(",");
double c = Double.valueOf(num[0]);
double d = Double.valueOf(num[1]);
if(a==c&&b==d){
System.out.print("Wrong Format");
return;
}
System.out.print(Math.sqrt((a-c)*(a-c)+(b-d)*(b-d)));
in.close();
}
}
这道题是计算两点之间的距离,虽说题目一目了然,但是对输入的数据要有很高的要求,只要输入的数据不符合坐标的形式,那就要程序报“"Wrong Format”,而且输入正确后也要注意坐标点的数量,超过了要求就会输出“wrong number of points”。在这里因为输入的数据中存在空格和逗号等字符,所以我们输入的时候也要选择字符串输入。再然后就是对数据的校验——是否有空格,逗号,小数点,加号和减号(而且不能同一个数里出现两个)的字符出现,接着好要注意空格和逗号的数量关系和位置关系,之后还要确定小数点后有没有数、整数位有没有出现只有两个零的情况等等,做好以上检验后就开始计算,我们可以用“split(" ")”这个方法来将我们输入的数组进行字符串按照空格分成两个坐标,再进行两次“split(",")”来获得两个坐标点x和y。之后再用“Double.parseDouble”来讲字符转换成double类型的x和y,最后再通过两点之间的距离公式(√(x1-x2)²+(y1-y2)²)来计算距离。
(2)圈复杂度:
参考SourceMonitor的生成报表内容以及PowerDesigner的相应类图

(3) 踩坑心得:
这道题的难点是在于数据的校验上,写这道题要考虑很多种输入错误的格式,稍微不注意就会漏掉一些测试点;重点就是正则表达式的输入数据的读取判读是否为合法输入,如果用常规的办法代码编程量大, 编程复杂容易出现编程错误和逻辑错误代码在重新检查会花费大量时间和精力, 但用正则表达式却只要几行甚至一行就可以了,非常省时省力,代码看起来还简单明了。
(4)改进建议:
判断字符串数组长度是否合格时,如果创建一个方法将字符串数组长度作为参数传递过去再判断是否合格会使此时的代码更简洁,同时也能减少圈复杂度。如果有办法能将for循环中判断格式是否正确的if语句减少或许能使代码的效率提高,而且易懂。
3.题目集三—7-2 点线形系列2-线的计算
(1)题目分析:用户输入一组选项和数据,进行与直线有关的计算。选项包括:
1:输入两点坐标,计算斜率,若线条垂直于X轴,输出"Slope does not exist"。
2:输入三个点坐标,输出第一个点与另外两点连线的垂直距离。
3:输入三个点坐标,判断三个点是否在一条线上,输出true或者false。
4:输入四个点坐标,判断前两个点所构成的直线与后两点构成的直线是否平行,输出true或者false.
5:输入四个点坐标,计算输出前两个点所构成的直线与后两点构成的直线的交点坐标,x、y坐标之间以英文分隔",",并输出交叉点是否在两条线段之内(不含四个端点)的判断结果(true/false),判断结果与坐标之间以一个英文空格分隔。若两条线平行,没有交叉点,则输出"is parallel lines,have no intersection point"。
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。
例如:1:0,0 1,1
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
不论哪个选项,如果格式、点数量都符合要求,但构成任一条线的两个点坐标重合,输出"points coincide",
输出格式:
见题目描述。
代码如下:
查看代码 import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
String s=input.nextLine();
String a=s.replace(":",",");
String num[] = a.split(",| ");
if(s.matches("1:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==5) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
if(x1==x2&&y1==y2)
System.out.print("points coincide");
else {
if(x1==x2)
System.out.print("Slope does not exist");
else {
double slope=(y1-y2)/(x1-x2);
System.out.print(slope);
}
}
}
else System.out.print("wrong number of points");
}
else if(s.matches("2:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==7) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x3==x2&&y3==y2))
System.out.print("points coincide");
else {
double distance=Math.abs((y3-y2)*x1+(x2-x3)*y1+x3*y2-y3*x2)/Math.sqrt((y3-y2)*(y3-y2)+(x3-x2)*(x3-x2));
System.out.print(distance);
}
}
else System.out.print("wrong number of points");
}
else if(s.matches("3:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==7) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x3==x2&&y3==y2))
System.out.print("points coincide");
else {
double slope1=(y1-y2)/(x1-x2),slope2=(y1-y2)/(x1-x3);
if(slope1==slope2)
System.out.print("true");
else
System.out.print("false");
}
}
else System.out.print("wrong number of points");
}
else if(s.matches("4:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==9) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
double x4 = Double.parseDouble(num[7]);
double y4 = Double.parseDouble(num[8]);
if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x1==x4&&y1==y4)||(x2==x3&&y2==y3)||(x2==x4&&y2==y4)||(x3==x4&&y3==y4))
System.out.print("points coincide");
else {
double slope1=(y1-y2)/(x1-x2),slope2=(y3-y4)/(x3-x4);
if(slope1==slope2)
System.out.print("true");
else
System.out.print("false");
}
}
else
System.out.print("wrong number of points");
}
else if(s.matches("5:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==9) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
double x4 = Double.parseDouble(num[7]);
double y4 = Double.parseDouble(num[8]);
if((x1==x2&&y1==y2)||(x3==x4&&y3==y4))
System.out.print("points coincide");
else {
double slope1=(y1-y2)/(x1-x2),slope2=(y3-y4)/(x3-x4);
if(slope1!=slope2) {
double x0=((x3-x4)*(y1*x2-x1*y2)-(x1-x2)*(y3*x4-x3*y4))/((y1-y2)*(x3-x4)-(y3-y4)*(x1-x2));
double y0=((y3-y4)*(y1*x2-x1*y2)-(y1-y2)*(y3*x4-x3*y4))/((y1-y2)*(x3-x4)-(y3-y4)*(x1-x2));
boolean judge=false;
if((Math.max(x1,x2)>=Math.min(x3,x4)&&Math.min(x1,x2)<=Math.max(x3,x4))&&(Math.max(y1,y2)>=Math.min(y3,y4)&&Math.min(y1,y2)<=Math.max(y3,y4))) {
if(((x3-x1)*(y2-y1)-(y3-y1)*(x2-x1))*((x4-x1)*(y2-y1)-(y4-y1)*(x2-x1))<=0&&((x1-x3)*(y4-y3)-(y1-y3)*(x4-x3))*((x2-x3)*(y4-y3)-(y2-y3)*(x4-x3))<=0)
judge=true;
}
if((x0==x1&&y0==y1)||(x0==x2&&y0==y2)||(x0==x3&&y0==y3)||(x0==x4&&y0==y4))
judge=false;
System.out.print(x0+","+y0+" "+judge);
}
else
System.out.print("is parallel lines,have no intersection point");
}
}
else
System.out.print("wrong number of points");
}
else
System.out.print("Wrong Format");
}
}
本题考查数组分段提取,并进行相关点距离的运算,我首先将用户输入的字符串进行长度判断,若长度不符合要求,则输出长度错误提醒用户,若长度无错误,截取前两个字符进行判断,若用户输入两个符合,则报错,否则截取后面的字符并用强制类型转换成两个坐标的横纵坐标。进行相关运算。
(2) 圈复杂度:
参考SourceMonitor的生成报表内容以及PowerDesigner的相应类图

(3)踩坑心得:
首先就是要理解题目,然后看清楚题目中每一个要求的输出结果,其次是对一些算法的熟悉;再者细节方面要注意两点重合和求一条线的斜率是要注意斜率不存在的情况,还有就是注意一个数除以0在程序中是不会报错而且是可以输出结果的,只是输出的结果会影响后续程序的运行;总的来说就是注意点线之间的一些数学关系,在写代码时要多加注意。
(4)改进建议:
此题较难,且用到很多数学计算的方法,要把它转化为java语言较难,并且对java类和对象的运用不太熟练,所以这道题目我没有用类的方法和对象的思维来写,而是只用了一个主类来解决问题。这道题我并没有拿到满分,还有格式上的判断和一个测试点过不了。此题用类应该能把自己的思路表达地更清晰,也能快速定位到自己地错误,也是为下一题打基础、做铺垫。
4.题目集三—7-3 点线形系列3-三角形的计算
(1)题目分析:用户输入一组选项和数据,进行与三角形有关的计算。选项包括:
1:输入三个点坐标,判断是否是等腰三角形、等边三角形,判断结果输出true/false,两个结果之间以一个英文空格符分隔。
2:输入三个点坐标,输出周长、面积、重心坐标,三个参数之间以一个英文空格分隔,坐标之间以英文","分隔。
3:输入三个点坐标,输出是钝角、直角还是锐角三角形,依次输出三个判断结果(true/false),以一个英文空格分隔,
4:输入五个点坐标,输出前两个点所在的直线与三个点所构成的三角形相交的交点数量,如果交点有两个,则按面积大小依次输出三角形被直线分割成两部分的面积。若直线与三角形一条线重合,输出"The point is on the edge of the triangle"
5:输入四个点坐标,输出第一个是否在后三个点所构成的三角形的内部(输出in the triangle/outof triangle)。
必须使用射线法,原理:由第一个点往任一方向做一射线,射线与三角形的边的交点(不含点本身)数量如果为1,则在三角形内部。如果交点有两个或0个,则在三角形之外。若点在三角形的某条边上,输出"on the triangle"
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
如果输入的三个点无法构成三角形,输出"data error"。
注意:输出的数据若小数点后超过6位,只保留小数点后6位,多余部分采用四舍五入规则进到最低位。小数点后若不足6位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333333,1.0按格式输出为1.0
选项4中所输入线的两个点坐标重合,输出"points coincide",
代码如下:
查看代码 import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String s=input.nextLine();
String a=s.replace(":",",");
String num[] = a.split(",| ");
input.close();
if(s.matches("1:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==7) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
boolean judge=false,judge1=false,judge2=false;
if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x2==x3&&y2==y3)||(x1==x2&&x1==x3))
judge=false;
else {
if(x1==x2||x1==x3||x2==x3)
judge=true;
else {
double slope1=(y1-y2)/(x1-x2);
double slope2=(y1-y3)/(x1-x3);
if(slope1!=slope2)
judge=true;
}
}
if(judge) {
double line1=(y1-y2)*(y1-y2)+(x1-x2)*(x1-x2);
double line2=(y1-y3)*(y1-y3)+(x1-x3)*(x1-x3);
double line3=(y2-y3)*(y2-y3)+(x2-x3)*(x2-x3);
if(line1==line2||line1==line3||line2==line3) {
judge1=true;
if(line1==line2&&line1==line3)
judge2=true;
}
System.out.print(judge1+" "+judge2);
}
else
System.out.print("data error");
}
else
System.out.print("wrong number of points");
}
else if(s.matches("2:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==7) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
boolean judge=false;
if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x2==x3&&y2==y3)||(x1==x2&&x1==x3))
judge=false;
else {
if(x1==x2||x1==x3||x2==x3)
judge=true;
else {
double slope1=(y1-y2)/(x1-x2);
double slope2=(y1-y3)/(x1-x3);
if(slope1!=slope2)
judge=true;
}
}
if(judge) {
double line1=Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2));
double line2=Math.sqrt((y1-y3)*(y1-y3)+(x1-x3)*(x1-x3));
double line3=Math.sqrt((y2-y3)*(y2-y3)+(x2-x3)*(x2-x3));
double circumference=line1+line2+line3;
double area=(x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2)/2;
double x0=(x1+x2+x3)/3;
double y0=(y1+y2+y3)/3;
if(circumference*1e+6%10!=0) {
String num1=String.format("%.6f",circumference);
System.out.print(num1+" ");
}
else
System.out.print(circumference+" ");
if(area*1e+6%10!=0) {
String num2=String.format("%.6f",area);
System.out.print(num2+" ");
}
else
System.out.print(area+" ");
if(x0*1e+6%10!=0) {
String num3=String.format("%.6f",x0);
System.out.print(num3+" ");
}
else
System.out.print(x0+",");
if(y0*1e+6%10!=0) {
String num4=String.format("%.6f",y0);
System.out.print(num4);
}
else
System.out.print(y0);
}
else
System.out.print("data error");
}
else
System.out.print("wrong number of points");
}
else if(s.matches("3:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==7) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
boolean judge=false,judge1=false,judge2=false,judge3=false;
if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x2==x3&&y2==y3)||(x1==x2&&x1==x3))
judge=false;
else {
if(x1==x2||x1==x3||x2==x3)
judge=true;
else {
double slope1=(y1-y2)/(x1-x2);
double slope2=(y1-y3)/(x1-x3);
if(slope1!=slope2)
judge=true;
}
}
if(judge) {
double line1=(y1-y2)*(y1-y2)+(x1-x2)*(x1-x2);
double line2=(y1-y3)*(y1-y3)+(x1-x3)*(x1-x3);
double line3=(y2-y3)*(y2-y3)+(x2-x3)*(x2-x3);
if(line1+line2>line3&&line1+line3>line2&&line2+line3>line1)
judge1=true;
else if(line1+line2==line3||line1+line3==line2&&line2+line3==line1)
judge2=true;
else
judge3=true;
System.out.print(judge3+" "+judge2+" "+judge1);
}
else
System.out.print("data error");
}
else
System.out.print("wrong number of points");
}
else if(s.matches("4:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==11) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
double x4 = Double.parseDouble(num[7]);
double y4 = Double.parseDouble(num[8]);
double x5 = Double.parseDouble(num[9]);
double y5 = Double.parseDouble(num[10]);
boolean judge=false;
if(x1==x2&&y1==y2)
System.out.print("points coincide");
else {
if((x3==x4&&y3==y4)||(x3==x5&&y3==y5)||(x4==x5&&y4==y5)||(x3==x4&&x3==x5))
judge=false;
else {
if(x3==x4||x3==x5||x4==x5)
judge=true;
else {
double slope1=(y3-y4)/(x3-x4);
double slope2=(y3-y5)/(x3-x5);
if(slope1!=slope2)
judge=true;
}
}
if(judge) {
double distance1=((y1-y2)*x3+(x2-x1)*y3+x1*y2-y1*x2)/Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2));
double distance2=((y1-y2)*x4+(x2-x1)*y4+x1*y2-y1*x2)/Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2));
double distance3=((y1-y2)*x5+(x2-x1)*y5+x1*y2-y1*x2)/Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2));
if((distance1>0&&distance2>0&&distance3>0)||(distance1<0&&distance2<0&&distance3<0))
System.out.print("0");
else if((distance1==0&&distance2*distance3>0)||(distance2==0&&distance1*distance3>0)||(distance3==0&&distance1*distance2>0))
System.out.print("1");
else if((distance1==0&&distance2==0)||(distance1==0&&distance3==0)||(distance2==0&&distance3==0))
System.out.print("The point is on the edge of the triangle");
else {
System.out.print("2 ");
}
}
else
System.out.print("data error");
}
}
else
System.out.print("wrong number of points");
}
else if(s.matches("5:([+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?\\s)+[+-]?[\\d]+(.[\\d]*)?,[+-]?[\\d]+(.[\\d]*)?")) {
if(num.length==9) {
double x1 = Double.parseDouble(num[1]);
double y1 = Double.parseDouble(num[2]);
double x2 = Double.parseDouble(num[3]);
double y2 = Double.parseDouble(num[4]);
double x3 = Double.parseDouble(num[5]);
double y3 = Double.parseDouble(num[6]);
double x4 = Double.parseDouble(num[7]);
double y4 = Double.parseDouble(num[8]);
boolean judge=false;
if((x2==x3&&y2==y3)||(x2==x4&&y2==y4)||(x3==x4&&y3==y4)||(x2==x3&&x2==x4))
judge=false;
else {
if(x2==x3||x2==x4||x3==x4)
judge=true;
else {
double slope1=(y2-y3)/(x2-x3);
double slope2=(y2-y4)/(x2-x4);
if(slope1!=slope2)
judge=true;
}
}
if(judge) {
double distance1=((y2-y3)*x1+(x3-x2)*y1+x2*y3-y2*x3)/Math.sqrt((y2-y3)*(y2-y3)+(x2-x3)*(x2-x3));
double distance2=((y2-y4)*x1+(x4-x2)*y1+x2*y4-y2*x4)/Math.sqrt((y2-y4)*(y2-y4)+(x2-x4)*(x2-x4));
double distance3=((y3-y4)*x1+(x4-x3)*y1+x3*y4-y3*x4)/Math.sqrt((y3-y4)*(y3-y4)+(x3-x4)*(x3-x4));
double area=(x2*y3+x3*y4+x4*y2-x2*y4-x3*y2-x4*y3)/2;
double area1=(x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2)/2;
double area2=(x1*y2+x2*y4+x4*y1-x1*y4-x2*y1-x4*y2)/2;
double area3=(x1*y4+x4*y3+x3*y1-x1*y3-x4*y1-x3*y4)/2;
if(area==(area1+area2+area3)) {
if(distance1==0||distance2==0||distance3==0)
System.out.print("on the triangle");
else
System.out.print("outof the triangle");
}
else
System.out.print("in the triangle");
}
else
System.out.print("data error");
}
else
System.out.print("wrong number of points");
}
else
System.out.print("Wrong Format");
}
}
本题考查数组分段提取,并进行相关点距离的运算,我首先将用户输入的字符串进行长度判断,若长度不符合要求,则输出长度错误提醒用户,若长度无错误,截取前两个字符进行判断,若用户输入两个符合,则报错,否则截取后面的字符并用强制类型转换成两个坐标的横纵坐标。进行相关运算。
(2)踩坑心得:
除了与前两题一样的被格式正误所困扰外,浮点数精度是一个很大地坑点,在运算中尽量减少对浮点数的乘除这样会带来误差,最明显的错误在于保留六位小数方面,如果乘除过多会使答案出错。在对数据做四舍五入的话,应该可以先对数据进行判定,再来根据判断结果输出是否四舍五入和保留位数。还有就是射线法,做之前应该先了解射线法怎么使用,再将其转化成Java语言,再进行求解。
(3)改进建议:
和前两题一样,此题我也没有用类的方法和对象的思维来做,并且这道题的难度在之前的基础上进一步提升,拿到的分更少了。此题非常考察对数学函数的使用,让我明白要做好这道题要好好地提升自己有关数学函数计算地思维,这样的话写这道题会更容易点,更轻松点。在进行有关数学的计算和精度的判断时,尽量减少对浮点数的乘除计算,以此来降低复杂度,提高精度。除此之外,还有格式的判断,尽量运用正则表达式,这样会使得写代码的工程量会少很多。
三、总结
通过本次PTA三次大作业的训练,我学到了很多知识,包括从最基本的语法、选择结构、循环结构到字符串和字符串函数以及处理,再到对类与对象的认识和理解,虽然我还对类和对象的使用不太熟练。特别是在第三次作业当中,我学到了很多关于点、线、三角形的数学计算公式和函数。同时我也认识到了自己的不足,对一些常用方法的不熟悉、对题目有些地方的不理解、获取知识的效率不高、敲代码的速度不快、写的代码不能高效地实现功能、而且代码不够简洁,十分冗杂等等。这三次作业中我仍然发现自己存在着许多的语法错误,在今后的学习中更应加强基础知识的学习,吃透书本中的内容及课堂中所学知识。我还要加强对类与对象的使用,使自己更加熟练掌握与运用,在今后的PTA作业中尽量使用类和对象的思维来编写程序。在JAVA这门课程的学习当中,老师主要通过实例给我们讲设计的思维和方法,具体的知识和语法主要还是靠自己自学,所以我们要培养自己自主学习和搜索网上资料学习的能力。但是我还是希望老师在课堂上也能给我们多讲一些语法知识,因为我觉得在课堂学到的知识会让我印象更深刻。 我认为PTA的作业老师可以多给一些测试样例,并且多给一些提示,这样会减少出错!
浙公网安备 33010602011771号