java前三次题目集总结与分析
一、前言
1、第一次和第二次题目集
题目难度较低,知识点主要还是比较接近C的设计风格,并未用上Java的类,套用了Java的格式,但内容还是面向过程的,题量适中
2、第三次题目集
题目难度高,知识点主要用上了Java的类,内容逐渐面向对象化的,题量少
以下主要对第三次题目集进行分析,再从第一、二次题目集中挑选一些题目进行分析
二、题目具体分析
1、题目集一/题目7-2:长度质量计量单位换算
(1)题目详情
长度、质量的计量有多重不同的计算体系,有标准的国际单位制:千克与米,也有各个国家自己的计量方法如:磅、英寸;1磅等于0.45359237千克,1英寸等于0.0254米,请编写程序实现国际单位制与英制之间的换算。
输入格式:两个浮点数,以空格分隔,第一个是质量(以千克为单位)、第二个是长度(以米为单位)。例如:0.45359237 0.0254。
输出格式:两个浮点数,以空格分隔,第一个是质量(以磅为单位)、第二个是长度(以英寸为单位)。例如:1.0 1.0。
(2)设计
读入两个浮点数数据,利用质量(磅) = 质量(千克)/ 0.45359237 和长度(英寸) = 长度(米)/ 0.0254进行计算得到结果
(3)源码
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner input = new Scanner(System.in); double wight = input.nextDouble(); double length = input.nextDouble(); double gwight = wight/0.45359237; double glength = length/0.0254; System.out.println((float)gwight+" "+(float)glength); } }
(4)代码分析
本题代码结构简单清晰,使用了典型的面向过程方法
测试如下:
分析:改码结构简单,复杂度较低
(2)踩坑心得
最后的输出值要转化为float类型,double类型的数据输出无法通过测试
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”。
(2)设计
分别进行数据个数校验,奇偶校验和停止位校验,最后输出情况类型,若三种校验均通过,则输出最终结果
(3)源码
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner input = new Scanner(System.in); String dataStream = input.nextLine(); char data; char [] data8 = new char[9]; int count = 0, i = 0, flag = 0, n = 0; int length = dataStream.length(); for(i=0;i<length;i++) { data = dataStream.charAt(i); if(data == '1') n++; } if(length < 11 || n == length) System.out.println("null data"); else { for(i=0;i<length;i++) { data = dataStream.charAt(i); if(data == '0' && i + 10 < length) { int j, onenum = 0;//记录1的个数 char validate;//停止位 for(j=0;j<9;j++)//提取8位数+奇校验位 { i++; data = dataStream.charAt(i); if(data == '1')//记录9位中1的个数 onenum++; data8[j] = data; } // System.out.println(onenum); onenum = onenum % 2;//0(偶数个,对应parityCheck为1)或1(奇数个,对应parityCheck为0) i++; validate = dataStream.charAt(i); // System.out.println(parityCheck+" "+validate); if(validate == '1' && onenum == 0) { count++; System.out.println(count+":"+"parity check error"); } else if(validate == '1' && onenum !=0)//可输出 { count++; System.out.print(count+":"); for(j=0;j<8;j++) System.out.print(data8[j]); System.out.print("\n"); } else { count++; System.out.println(count+":"+"validate error"); } } } }//else } }
(4)代码分析
最大复杂度较高,平均复杂度也高,原因是没有分类,代码只有一个主类,然后所有功能都堆积在一个类里,导致主类结构复杂
(5)踩坑心得
第一次提交时,19-21三个测试点总是过不去,原因有点蠢,属于格式问题,多看了几遍题目才发现,它的输出是
这样子的,而我的是这样子的
改完之后就好了
(6)改进建议
可以将null data 融入到下面的for循环中,可以减少一个for循环
可以用面向对象的方式思考这个题目,可以极大地降低复杂度
3、题目集三/题目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
(2)设计
我将代码分割成了4个类,点类、输入输出类、非法格式判断类和主类,
其中点类包含点的坐标属性以及计算两点间距离的方法;输入输出类包含从控制台输入数据的方法和输出非法格式判断结果的方法;非法格式判断类只包含一个非法判断的方法;主类将以上三个类联系在一起。
(3)源码
import java.util.Scanner; class Spot {//点 double x, y; public double distanceCount(Spot a){//两点计算距离 double julix = Math.pow(this.x - a.x,2); double juliy = Math.pow(this.y - a.y,2); return Math.sqrt(julix + juliy); } } class InOutput { public String Input(){//输入 Scanner in = new Scanner(System.in); String s = in.nextLine(); return s; } public void Output(int a){//输出 if(a == 0) System.out.println("Wrong Format"); if(a == 2) System.out.println("wrong number of points"); } } class Verify {//非法输入匹配 public int feifa(String s) { String[] tokens = s.split(",| "); int i = 0, sign = 1; boolean flag = true; for(i=0;i<tokens.length;i++) { flag = tokens[i].matches("^[+-]?[1-9]\\d*\\.\\d+$|^[+-]?0\\.\\d+$|^[+-]?[1-9]\\d*$|^[+-]?0$"); if (!flag){//flag = flase sign = 0; break; } } if(flag && tokens.length!=4){//flag = true sign = 2; } return sign;//为1输入合法,为0输入格式错误,为2输入个数错误 } } public class Main { public static void main(String[] args) { InOutput input = new InOutput(); String s = input.Input(); Verify ver = new Verify();//非法检验 int sign = ver.feifa(s); input.Output(sign); if(sign == 1){//输入合法 String[] tokens = s.split(",| "); Spot dot1 = new Spot(); dot1.x = Double.valueOf(tokens[0]); dot1.y = Double.valueOf(tokens[1]); Spot dot2 = new Spot(); dot2.x = Double.valueOf(tokens[2]); dot2.y = Double.valueOf(tokens[3]); System.out.println(dot1.distanceCount(dot2)); } } }
(4)代码分析
此题的代码写的较为成功,复杂度大多在可接受范围内,但平均深度较高
(5)踩坑心得
正则表达式一直测试不正确导致测试点过不去,最后参考了一下网上大佬们写的“^[+-]?[1-9]\\d*\\.\\d+$|^[+-]?0\\.\\d+$|^[+-]?[1-9]\\d*$|^[+-]?0$”
其他地方没啥问题,这个题目的思路挺清晰的
(6)改进建议
感觉这样分类已经是我的天花板了,没啥改进想法,整体代码结构也不复杂,没啥好改进的
1、题目集三/题目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;如果不符合基本格式,输出"Wrong Format";如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points";不论哪个选项,如果格式、点数量都符合要求,但构成任一条线的两个点坐标重合,输出"points coincide"。
输出格式:见题目描述。
(2)设计
将代码分割成了5个类,点类、线类、输入输出类、非法格式判断类和主类,
其中点类包含录入点的坐标以及分别得到点的横纵坐标以及判断两点是否重合的方法;
线类包含与线有关的方法;
输入输出类包含从控制台输入数据的方法和输出非法格式判断结果的方法;
非法格式判断类只包含一个非法判断的方法;
主类将以上4个类联系在一起。
(3)源码
import java.util.Scanner; import java.math.BigDecimal; class Spot {//点 private double x, y; public void get(double a,double b){ this.x = a; this.y = b; } public double getx(){//得到x值 return this.x; } public double gety(){//得到y值 return this.y; } public int coincideDot(Spot d){//判断两点是否重合 int flag = 1; if((this.x == d.x) && (this.y == d.y)){ flag = 0;//两点重合 } return flag; } } class InOutput { public String Input(){//输入 Scanner in = new Scanner(System.in); String s = in.nextLine(); return s; } public void Output(int a){//输出 if(a == 0) System.out.println("Wrong Format"); if(a == 2) System.out.println("wrong number of points"); } } class Verify {//格式验证 public int feifa(String s,int dex){ String[] tokens = s.split(" "); int i = 0, sign = 1; boolean flag = true; for(i=0;i<tokens.length;i++) { if(i==0){ flag = tokens[i].matches("^[1-5]:[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); } else{ flag = tokens[i].matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); } if (!flag){//flag = flase sign = 0; break; } } if(flag && tokens.length!=(dex)){//flag = true sign = 2; } // System.out.println(sign); return sign;//为1输入合法,为0输入格式错误,为2输入个数错误 } } class Line {//线 public void slopeCompute(Spot dot1,Spot dot2) {//斜率计算 if(dot1.getx() == dot2.getx()){//斜率无穷大 System.out.println("Slope does not exist"); } else{//斜率存在(包括为0) System.out.println((dot1.gety() - dot2.gety())/(dot1.getx() - dot2.getx())); } } public double slopeGet(Spot dot1,Spot dot2) {//斜率计算 return (dot1.gety() - dot2.gety())/(dot1.getx() - dot2.getx()); } public double constantCompute(double k,Spot dot){//常数计算 return (dot.gety() - k * dot.getx()); } public double distancceCompute(Spot dot1,Spot dot2,Spot dot3){//点到线的距离计算 double distance = 0; if(dot2.getx() == dot3.getx()) {//斜率无穷大 distance = Math.abs(dot1.getx() - dot2.getx()); } else{ double k = slopeGet(dot2,dot3);//斜率 double b = constantCompute(k,dot2);//常数 distance = Math.abs(dot1.gety() - k*dot1.getx() - b) / Math.sqrt(Math.pow(k,2)+1.0); } return distance; } public int judge(Spot dot1,Spot dot2,Spot dot3){//判断三点是否在一条线上 int flag = 0;//不共线 if(dot1.getx()==dot2.getx() && dot3.getx()==dot1.getx()){//斜率无穷大 flag = 1;//共线 } else{ double k = slopeGet(dot2,dot3);//斜率 double b = constantCompute(k,dot2);//常数 if(dot1.gety() - k*dot1.getx() - b == 0){ flag = 1;//共线 } } return flag; } public int judgePingxing(Spot dot1,Spot dot2,Spot dot3,Spot dot4){//判断两线是否平行 int flag = 0;//不平行 if(dot1.getx() == dot2.getx() && dot3.getx() == dot4.getx()){//两线均垂直x轴 flag = 1;//平行 } else{ if(slopeGet(dot1,dot2) == slopeGet(dot3,dot4)){ flag = 1;//平行 } } return flag; } public void jiaoDian(Spot dot1,Spot dot2,Spot dot3,Spot dot4){//计算与判断交点 if(judgePingxing(dot1,dot2,dot3,dot4) == 1){//两线平行 System.out.println("is parallel lines,have no intersection point"); } else{ double k1 = 0, k2 = 0, b1 = 0, b2 = 0, x = 0, y = 0; int flag = 0; if(dot1.getx() == dot2.getx()){//第一根线斜率不存在 x = dot1.getx(); k2 = slopeGet(dot3,dot4);//斜率 b2 = constantCompute(k2,dot3); y = k2 * x + b2; y = Math.round(y*1000000000)/(double)1000000000; if(((x>dot3.getx()&&x<dot4.getx())||(x>dot4.getx()&&x<dot3.getx())) || ((y>dot1.gety()&&y<dot2.gety())||(y>dot2.gety()&&y<dot1.gety()))){ flag = 1; } } else if(dot3.getx() == dot4.getx()){//第二根线斜率不存在 x = dot3.getx(); k1 = slopeGet(dot1,dot2); b1 = constantCompute(k1,dot1); y = k1 * x + b1; y = Math.round(y*1000000000)/(double)1000000000;; if(((x>dot1.getx()&&x<dot2.getx())||(x>dot2.getx()&&x<dot1.getx())) || ((y>dot3.gety()&&y<dot4.gety())||(y>dot4.gety()&&y<dot3.gety()))){ flag = 1; } } else{ k1 = slopeGet(dot1,dot2);//斜率 b1 = constantCompute(k1,dot1);//常数 k2 = slopeGet(dot3,dot4);//斜率 b2 = constantCompute(k2,dot3);//常数 x = (b2-b1)/(k1-k2); // System.out.println("x:"+x); x = Math.floor(x*1000000000)/(double)1000000000; // System.out.println(x); y = k1 * x + b1; y = Math.floor(y*1000000000)/(double)1000000000; // System.out.println("k1:"+k1+" "+"k2:"+k2); // System.out.println(x+" "+y); if(((x>dot1.getx()&&x<dot2.getx()) || (x>dot2.getx()&&x<dot1.getx())) || ((x>dot3.getx()&&x<dot4.getx())||(x>dot4.getx()&&x<dot3.getx()))){ flag = 1; } } if(flag==1){ System.out.println(x+","+y+" "+"true"); } else{ System.out.println(x+","+y+" "+"flase"); } } } } public class Main { public static void main(String[] args) { // System.out.println("请输入一串字符:"); InOutput input = new InOutput(); String s = input.Input(); int selectNum = (int)s.charAt(0) - (int)'0'; int dex = 0, sign = 3;//dex为点的个数 String[] tokens = s.split(":|,| "); Verify ver = new Verify(); switch (selectNum){ case 1: dex = 2; sign = ver.feifa(s,dex);//判非法 input.Output(sign); if(sign==1){//合法 Spot dot1 = new Spot(); dot1.get(Double.valueOf(tokens[1]),Double.valueOf(tokens[2])); Spot dot2 = new Spot(); dot2.get(Double.valueOf(tokens[3]),Double.valueOf(tokens[4])); // System.out.println(dot1.getx()+" "+dot1.gety()); int flag = dot1.coincideDot(dot2); if(flag == 0){//两点重合 System.out.println("points coincide"); break; } else{//两点不重合,可计算斜率 Line line = new Line(); line.slopeCompute(dot1,dot2); } } break; case 2: dex = 3; sign = ver.feifa(s,dex); input.Output(sign); if(sign==1){//合法 Spot dot1 = new Spot(); dot1.get(Double.valueOf(tokens[1]),Double.valueOf(tokens[2])); Spot dot2 = new Spot(); dot2.get(Double.valueOf(tokens[3]),Double.valueOf(tokens[4])); Spot dot3 = new Spot(); dot3.get(Double.valueOf(tokens[5]),Double.valueOf(tokens[6])); if(dot1.coincideDot(dot2)==0 || dot1.coincideDot(dot3)==0 || dot2.coincideDot(dot3)==0){ System.out.println("points coincide"); break; } else{//点不重合 System.out.println("true"); Line line = new Line(); double dis = line.distancceCompute(dot1,dot2,dot3); System.out.println(dis); } } break; case 3: dex = 3; sign = ver.feifa(s,dex); input.Output(sign); if(sign==1){ Spot dot1 = new Spot(); dot1.get(Double.valueOf(tokens[1]),Double.valueOf(tokens[2])); Spot dot2 = new Spot(); dot2.get(Double.valueOf(tokens[3]),Double.valueOf(tokens[4])); Spot dot3 = new Spot(); dot3.get(Double.valueOf(tokens[5]),Double.valueOf(tokens[6])); if(dot1.coincideDot(dot2)==0 || dot1.coincideDot(dot3)==0 || dot2.coincideDot(dot3)==0){ System.out.println("points coincide"); break; } else{//点不重合 System.out.println("true"); Line line = new Line(); int flag = line.judge(dot1,dot2,dot3); if(flag == 0){//不共线 System.out.println("false"); } else{ System.out.println("true"); } } } break; case 4: dex = 4; sign = ver.feifa(s,dex); input.Output(sign); if(sign==1){ Spot dot1 = new Spot(); dot1.get(Double.valueOf(tokens[1]),Double.valueOf(tokens[2])); Spot dot2 = new Spot(); dot2.get(Double.valueOf(tokens[3]),Double.valueOf(tokens[4])); Spot dot3 = new Spot(); dot3.get(Double.valueOf(tokens[5]),Double.valueOf(tokens[6])); Spot dot4 = new Spot(); dot4.get(Double.valueOf(tokens[7]),Double.valueOf(tokens[8])); if(dot1.coincideDot(dot2)==0 || dot3.coincideDot(dot4)==0){ System.out.println("points coincide"); break; } else{//不重合 Line line = new Line(); int flag = line.judgePingxing(dot1,dot2,dot3,dot4); if(flag == 0){//不平行 System.out.println("false"); } else{ System.out.println("true"); } } } break; case 5: dex = 4; sign = ver.feifa(s,dex); input.Output(sign); if(sign==1){ Spot dot1 = new Spot(); dot1.get(Double.valueOf(tokens[1]),Double.valueOf(tokens[2])); Spot dot2 = new Spot(); dot2.get(Double.valueOf(tokens[3]),Double.valueOf(tokens[4])); Spot dot3 = new Spot(); dot3.get(Double.valueOf(tokens[5]),Double.valueOf(tokens[6])); Spot dot4 = new Spot(); dot4.get(Double.valueOf(tokens[7]),Double.valueOf(tokens[8])); if(dot1.coincideDot(dot2)==0 || dot3.coincideDot(dot4)==0){ System.out.println("points coincide"); break; } else{ Line line = new Line(); line.jiaoDian(dot1,dot2,dot3,dot4); } } break; default: System.out.println("Wrong Format"); break; } } }
(4)代码分析
代码复杂度较高,最大复杂度和平均复杂度都超过了合适的范围,原因在于对于类的掌握还不到位,比如说线的类完全没有做出来,里面都是方法,也就是说线类完全可以被点类替代
(5)踩坑心得
有一个格式验证的测试点无法通过,后来发现是判断方法有误,一开始我用逗号和空格同时split字符串,这也就意味着如果测试用例把逗号和空格的位置互换就会出现错的格式判为正确的情况,改为只用空格拆分,测试点就过了
第五种情况的计算交点有三个点一直过不了,然后怀疑是double精度原因导致数据在边界值出现误差造成结果错误,但改来改去还是没改好......
(6)改进建议
类的封装度不够高,类还没有完全独立建立起来,可以在线里面添加属性点
7、题目集三/题目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",
(2)设计
将代码分割成了6个类,点类、线类、三角形类、输入输出类、非法格式判断类和主类,其中点类包含点的坐标属性、判断两点是否重合的方法以及两点间距离计算的方法;线类包含线的相关属性以及与线有关的方法;三角形类包含三角形的相关属性以及与线有关的方法;输入输出类包含从控制台输入数据的方法、输出非法格式判断结果和输出三角形判断结果的方法;非法格式判断类只包含一个非法判断的方法;主类将以上5个类联系在一起。
(3)源码
import java.util.Scanner; class InOutput { public String Input(){//输入 Scanner in = new Scanner(System.in); String s = in.nextLine(); return s; } public void Output(int a){//输出非法判断 if(a == 0) System.out.println("Wrong Format"); if(a == 2) System.out.println("wrong number of points"); } public void outPut1(int a){//0为既不等腰也不等边,1为等腰,2为等边(包含等腰) if(a==0){ System.out.println("false flase"); } else if(a==1){ System.out.println("true false"); } else{ System.out.println("true true"); } } public void outPut2(int a){//0为直角,1为钝角,2为锐角,输出顺序为钝角,直角,锐角 if(a==0){ System.out.println("false true false"); } else if(a==1){ System.out.println("true false false"); } else{ System.out.println("false false true"); } } } class Verify {//格式验证 public int feifa(String s, int dex){ String[] tokens = s.split(" "); int i = 0, sign = 1; boolean flag = true; for(i=0;i<tokens.length;i++) { if(i==0){ flag = tokens[i].matches("^[1-5]:[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); } else{ flag = tokens[i].matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?),[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$"); } if (!flag){//flag = flase sign = 0; break; } } if(flag && tokens.length!=(dex)){//flag = true sign = 2; } // System.out.println(sign); return sign;//为1输入合法,为0输入格式错误,为2输入个数错误 } } class Spot{//点类 double x, y;//横纵坐标 public int coincideDot(Spot dot1,Spot dot2){//判断两点是否重合 int flag = 1;//不重合 if((dot1.x == dot2.x) && (dot1.y == dot2.y)){ flag = 0;//两点重合 } return flag; } public double lengthCompute(Spot dot1, Spot dot2){//两点间距离(线段长度)计算 return (Math.sqrt((dot1.x-dot2.x)*(dot1.x-dot2.x)+(dot1.y-dot2.y)*(dot1.y-dot2.y))); } } class Line{//线类 Spot dot1 = new Spot(); Spot dot2 = new Spot();//两点确定一条直线 double length;//两点间距离 double k;//斜率 int xielvFlag;//标记斜率是否存在(为0不存在,为1存在) double b;//常数 public void creatLine(String[] a, Line l){//直线信息录入 l.dot1.x = Double.valueOf(a[1]); l.dot1.y = Double.valueOf(a[2]); l.dot2.x = Double.valueOf(a[3]); l.dot2.y = Double.valueOf(a[4]); l.length = lengthCount(l); l.k = xielvCount(l); l.xielvFlag = xielvJudge(l); l.b = constantCompute(l); } public double lengthCount(Line l){//两点间距离(线段长度)计算 return (Math.sqrt((l.dot1.x-l.dot2.x)*(l.dot1.x-l.dot2.x)+(l.dot1.y-l.dot2.y)*(l.dot1.y-l.dot2.y))); } public double distancceCompute(Line l, Spot dot){//点到线的距离计算 double distance = 0; return distance; } public double xielvCount(Line l){//线的斜率计算 return (l.dot1.y-l.dot2.y)/(l.dot1.x-l.dot2.x); } public int xielvJudge(Line l){//线的斜率判断 if(l.dot1.x == l.dot2.x)//斜率不存在 return 0; else return 1; } public boolean coincideJudge(Line l){//判断线的端点是否重合 if((l.dot1.x == l.dot2.x) && (l.dot1.y == l.dot2.y)){//重合 return false; } else{ return true; } } public double constantCompute(Line l){//常数计算 return (l.dot1.y - k * l.dot1.x); } public boolean dotExistLine(Line l, Spot dot){//判断点是否在线上,在返回true,不在返回false if(dot.y - l.k * dot.x - l.b < 0.000001)//在线上 return true; else return false; } public Spot jiaodianCount(Line l1, Line l2,Spot dot){//求两条相交直线的交点 dot.x = (l2.b - l1.b)/(l1.k - l2.k); dot.y = l1.k * dot.x + l1.b; return dot; } public boolean dianXianduan(Spot dot, Line l){//判断点是否在线段上 if(l.dot1.x == l.dot2.x){//斜率不存在 if((dot.y >= l.dot1.y && dot.y <= l.dot2.y) || (dot.y >= l.dot2.y && dot.y <= l.dot1.y))//在 return true; else return false; } else if(l.k == 0){ if((dot.x >= l.dot1.x && dot.x <= l.dot2.x) || (dot.x >= l.dot2.x && dot.x <= l.dot1.x))//在 return true; else return false; } else if(l.k > 0){ if(((dot.x >= l.dot1.x && dot.x <= l.dot2.x) && (dot.y >= l.dot1.x && dot.y <= l.dot2.x)) || ((dot.x >= l.dot2.x && dot.x <= l.dot1.x) && (dot.y >= l.dot2.x && dot.y <= l.dot1.x)))//在 return true; else return false; } else{//l.k<0 if(((dot.x >= l.dot1.x && dot.x <= l.dot2.x) && (dot.y >= l.dot2.x && dot.y <= l.dot1.x)) || ((dot.x >= l.dot2.x && dot.x <= l.dot1.x) && (dot.y >= l.dot1.x && dot.y <= l.dot2.x))) return true; else return false; } } } class Triangle{//三角形类 Spot dot1 = new Spot(); Spot dot2 = new Spot(); Spot dot3 = new Spot();//三角形三个顶点 Line l1 = new Line(); Line l2 = new Line(); Line l3 = new Line();//三角形三条边 public void creatTriangle(int start, String[] a, Triangle t){//输入三角形信息 t.dot1.x = Double.valueOf(a[start]); t.dot1.y = Double.valueOf(a[++start]); t.dot2.x = Double.valueOf(a[++start]); t.dot2.y = Double.valueOf(a[++start]); t.dot3.x = Double.valueOf(a[++start]); t.dot3.y = Double.valueOf(a[++start]);//顶点信息 t.l1.dot1 = t.dot1; t.l1.dot2 = t.dot2;//l1端点dot1,dot2 t.l2.dot1 = t.dot1; t.l2.dot2 = t.dot3;//l2端点dot1,dot3 t.l3.dot1 = t.dot2; t.l3.dot2 = t.dot3;//l3端点dot2,dot3 t.l1.length = t.l1.lengthCount(t.l1); t.l2.length = t.l2.lengthCount(t.l2); t.l3.length = t.l3.lengthCount(t.l3);//三角形三边长度 t.l1.k = t.l1.xielvCount(t.l1); t.l2.k = t.l2.xielvCount(t.l2); t.l3.k = t.l3.xielvCount(t.l3);//三边所在直线的斜率 t.l1.xielvFlag = t.l1.xielvJudge(t.l1); t.l2.xielvFlag = t.l2.xielvJudge(t.l2); t.l3.xielvFlag = t.l3.xielvJudge(t.l3);//三边所在直线斜率存在标记 t.l1.b = t.l1.constantCompute(t.l1); t.l2.b = t.l2.constantCompute(t.l2); t.l3.b = t.l3.constantCompute(t.l3);//常数 } public boolean gouChengTriangle(Triangle t){//判断能否构成三角形 boolean flag = false; if((t.l1.length-t.l2.length-t.l3.length<0) && (t.l2.length-t.l1.length-t.l3.length<0) && (t.l3.length-t.l1.length-t.l2.length<0)) flag = true; // System.out.println(flag); return flag; } public int dengyaoDengbianJudge(Triangle t){//判断三角形是否等腰、是否等边 //0为既不等腰也不等边,1为等腰,2为等边(包含等腰) int flag = 3; if((t.l1.length==t.l2.length) || (t.l1.length == t.l3.length) || (t.l2.length == t.l3.length)){ if(t.l1.length == t.l2.length && t.l1.length == t.l3.length){//等边 flag = 2; } else{//等腰 flag = 1; } } else{ flag = 0; } return flag; } public int triangleJudge(Triangle t){//三角形判断,0为直角,1为钝角,2为锐角 double a = t.l1.length; double b = t.l2.length; double c = t.l3.length; int flag = 3; if(a * a == b * b + c * c || b * b == a * a + c * c || c * c == a * a + b * b){//直角 flag = 0; } else if(a * a > b * b + c * c || b * b > a * a + c * c || c * c > a * a + b * b){//钝角 flag = 1; } else{//锐角 flag = 2; } return flag; } public boolean lineCoinTriangle(Line l, Triangle t){//判断线与三角形三边是否重合 if(l.k == t.l1.k){//l与l1斜率相等 if(l.dotExistLine(l,t.l1.dot1)){//点在线上 return false; } else{ return true; } } else if(l.k == t.l2.k){//l与l2斜率相等 if(l.dotExistLine(l,t.l2.dot1)){//点在线上 return false; } else{ return true; } } else if(l.k == t.l3.k){//l与l3斜率相等 if(l.dotExistLine(l,t.l3.dot1)){//点在线上 return false; } else{ return true; } } else//不重合 return true; } public void lineSplitTriangle(Line l, Triangle t){//直线分割三角形 int dotL1 = 0, dotL2 = 0, dotL3 = 0; Spot dot1 = new Spot();//记录三个交点,不平行必然有交点 Spot dot2 = new Spot(); Spot dot3 = new Spot(); if(l.k == t.l1.k){//平行 dotL1 = 0; } else{ dot1 = l.jiaodianCount(l, t.l1, dot1); if(l.dianXianduan(dot1,t.l1)){//点在边上 dotL1 = 1; } else{ dotL1 = 0; } } if(l.k == t.l2.k){//平行 dotL2 = 0; } else{ dot2 = l.jiaodianCount(l, t.l2, dot2); if(l.dianXianduan(dot2,t.l2)){//点在边上 dotL2 = 1; } else{ dotL2 = 0; } } if(l.k == t.l3.k){//平行 dotL3 = 0; } else{ dot3 = l.jiaodianCount(l, t.l3, dot3); if(l.dianXianduan(dot3,t.l3)){//点在边上 dotL3 = 1; } else{ dotL3 = 0; } } int dotL = dotL1 + dotL2 + dotL3;//总交点个数,可能包含重复 if(dot1.coincideDot(dot1, dot2) == 0 && dotL1==1 && dotL2==1){//重合 dotL--; } else if(dot1.coincideDot(dot1, dot3) == 0 && dotL1==1 && dotL3==1){ dotL--; } else if(dot2.coincideDot(dot2, dot3) == 0 && dotL2==1 && dotL3==1){ dotL--; } System.out.print(dotL); if(dotL == 2){ double a = 0,b = 0,c = 0,p = 0,area1 = 0,area2 = 0; double p1 = (t.l1.length + t.l2.length + t.l3.length)/2.0; double area = Math.sqrt(p1*(p1-t.l1.length)*(p1-t.l2.length)*(p1-t.l3.length));//总面积 if(dotL1==1 && dotL2==1){//t.dot1, dot1, dot2 a = t.dot1.lengthCompute(t.dot1, dot1); b = t.dot1.lengthCompute(t.dot1, dot2); c = dot1.lengthCompute(dot1, dot2); } else if(dotL1==1 && dotL3==1){//t.dot2, dot1, dot3 a = t.dot2.lengthCompute(t.dot2, dot1); b = t.dot2.lengthCompute(t.dot2, dot3); c = dot1.lengthCompute(dot1, dot3); } else if(dotL2==1 && dotL3==1){//t.dot3, dot2, dot3 a = t.dot3.lengthCompute(t.dot3, dot2); b = t.dot3.lengthCompute(t.dot3, dot3); c = dot2.lengthCompute(dot2, dot3); } p = (a+b+c)/2.0; area1 = Math.sqrt(p*(p-a)*(p-b)*(p-c)); area2 = area - area1; area1 = (int)(area1*1000000+0.5)/(double)1000000; area2 = (int)(area2*1000000+0.5)/(double)1000000; if(area1 < area2){ double temp = area1; area1 = area2; area2 = temp; } System.out.println(" "+area1+" "+area2); } } } public class Main{ public static void main(String[] args){ //输入 InOutput input = new InOutput(); String s = input.Input(); int selectNum = (int)s.charAt(0) - (int)'0';//情况选择 int dex = 0, sign = 3;//dex为点的个数,sign应该取0,1,2以外的值 String[] tokens = s.split(":|,| "); //判非法 Verify ver = new Verify(); switch(selectNum){ case 1: dex = 3; sign = ver.feifa(s,dex);//判非法 input.Output(sign); if(sign == 1){//合法 Triangle t = new Triangle(); int start = 1; t.creatTriangle(start,tokens,t);//三角形信息录入,包括三点信息、三边长度和端点信息 if(!t.gouChengTriangle(t)){ System.out.println("data error"); break; } int flag = 3;//0为既不等腰也不等边,1为等腰,2为等边(包含等腰) flag = t.dengyaoDengbianJudge(t); input.outPut1(flag); } break; case 2: dex = 3; sign = ver.feifa(s,dex);//判非法 input.Output(sign); if(sign == 1){//合法 Triangle t = new Triangle(); int start = 1; t.creatTriangle(start,tokens,t);//三角形信息录入,包括三点信息、三边长度和端点信息 if(!t.gouChengTriangle(t)){ System.out.println("data error"); break; } double zhouchang = t.l1.length + t.l2.length + t.l3.length; double p = zhouchang/2.0; double mianji = Math.sqrt(p*(p-t.l1.length)*(p-t.l2.length)*(p-t.l3.length)); double x = (t.dot1.x+t.dot2.x+t.dot3.x)/3.0; double y = (t.dot1.y+t.dot2.y+t.dot3.y)/3.0; zhouchang = (int)(zhouchang*1000000+0.5)/(double)1000000; mianji = (int)(mianji*1000000+0.5)/(double)1000000; x = (int)(x*1000000+0.5)/(double)1000000; y = (int)(y*1000000+0.5)/(double)1000000; System.out.println(zhouchang+" "+ mianji +" "+x+","+y); } break; case 3: dex = 3; sign = ver.feifa(s,dex);//判非法 input.Output(sign); if(sign == 1){//合法 Triangle t = new Triangle(); int start = 1; t.creatTriangle(start,tokens,t);//三角形信息录入,包括三点信息、三边长度和端点信息 if(!t.gouChengTriangle(t)){ System.out.println("data error"); break; } int flag = t.triangleJudge(t);//钝角、直角、锐角判断,0为直角,1为钝角,2为锐角 input.outPut2(flag); } break; case 4: dex = 5; sign = ver.feifa(s,dex);//判非法 input.Output(sign); if(sign == 1){//合法 Triangle t = new Triangle(); int start = 5; t.creatTriangle(start,tokens,t);//三角形信息录入,包括三点信息、三边长度和端点信息 Line l = new Line(); l.creatLine(tokens,l);//直线信息录入 if(!l.coincideJudge(l)){ System.out.println("points coincide"); break; } if(!t.gouChengTriangle(t)){ System.out.println("data error"); break; } if(!t.lineCoinTriangle(l,t)){//线与三角形三边重合 System.out.println("The point is on the edge of the triangle"); break; } else{ t.lineSplitTriangle(l,t);//直线分割三角形 } } break; case 5: dex = 4; sign = ver.feifa(s,dex);//判非法 input.Output(sign); if(sign == 1){//合法 Triangle t = new Triangle(); int start = 3; t.creatTriangle(start,tokens,t);//三角形信息录入,包括三点信息、三边长度和端点信息 if(!t.gouChengTriangle(t)){ System.out.println("data error"); break; } Spot dot = new Spot(); double dodt1 = dot.lengthCompute(dot, t.dot1); double dodt2 = dot.lengthCompute(dot, t.dot2); double dodt3 = dot.lengthCompute(dot, t.dot3); double area1 = area(dodt1, dodt2, t.l1.length); double area2 = area(dodt1, dodt3, t.l2.length); double area3 = area(dodt2, dodt3, t.l3.length); double area0 = area(t.l1.length, t.l2.length, t.l3.length); if(area1+area2+area3 == area0){ System.out.println("in the triangle"); } else if(area1+area2+area3 > area0){ System.out.println("outof the triangle"); } else{ System.out.println("on the triangle"); } } break; default: System.out.println("Wrong Format"); break; }//switch } public static double area(double a, double b, double c){ double p = (a+b+c)/2.0; return (p*(p-a)*(p-b)*(p-c)); } }
(4)代码分析
本次代码复杂度可以接受,但最大深度以及平均深度很大,原因应该是方法内的一些运算可以单独拎出来作为一个方法,但我并没有,而是所有直接堆在一个方法里,然后方法间的调用又比较复杂
(5)踩坑心得
由于当时直接将前一题对线的用法直接搬过来了,然后格式验证有问题,改好线的再搬过来就好了,第四个测试点全部没过,找了很久完全没进度,呜呜呜呜呜呜呜
(6)改进建议
方法简化
三、总结
这三次题目做下来,感觉对于Java的应用慢慢的得到完善,从一开始的完全面对过程写码,到后来慢慢分成一个个类,再慢慢的完善单个的类,虽然结果没出来,但我觉得以后肯定可以的!!!!对于数据类型的应用范围以及许多库函数的应用。