返回顶部

java作业前三次总结

1. 前言

说给第一次接触java语法的我:

       在大一接触了c/c++语言,大二接触了python语言的情况下,java语法对我来说不能说是学的很艰难,各种编程语言只是承载体,必然会有许多相似的地方。更重要的学习应该是编程思想而不是语言,比如面对过程编程,面对函数编程,面对对象编程etc...本次学习的正是面对对象编程。在大一时学习算法时,频繁使用的c++STL其实就是类,曾经为了使用方便自己亲手封装过高精度,ac自动机,sam等struct结构体,算是我第一次封装类。在大二时写一个三小项目时,用python封装过功能全面一点的类...

       在这之前也只是稍微学习了有关类的知识,知道类的概念和使用,希望通过java和这门课程系统全面地学习面对对象编程的思想。


对于前三次的作业:

       第一次作业我认为最大的难点第一次接触java语法,只能通过网络搜索+其他编程语言的语法来尝试;

       第二次作业我认为最大的难点是java数组的特殊性,和String类的相关API的学习;

       第三次作业我认为最大的难点是浮点数计算的精度丢失,而PTA的测试点为文本对比


2. 设计与分析

2.1. practice 1

2.1.1. 身体质量指数(BMI)测算

  • 思路

       个人认为是输入输出题,只要注意题目给出的数据范围就行

  • 实现
//身体质量指数(BMI)测算
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        double weight = sc.nextDouble();
        double height = sc.nextDouble();


        //check
        if (weight>727 || weight<=0){
            System.out.println("input out of range");
            return;
        }
        if (height>2.72 || height<=0){
            System.out.println("input out of range");
            return;
        }

        //judge
        double tmp = weight / Math.pow(height,2);
        if( tmp < 18.5){
            System.out.println("thin");
            return;
        }
        if( tmp >= 24){
            if ( tmp >= 28){
                System.out.println("fat");
                return;
            }
            System.out.println("overweight");
            return;
        }
        System.out.println("fit");

    }
}


2.1.2. 长度质量计量单位换算

  • 思路:

    个人认为是语法题,注意数据范围,注意数据类型要转换为float型

  • 实现:

//长度质量计量单位换算
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        double m = sc.nextDouble();
        double len = sc.nextDouble();

        System.out.println( (float)(m /  0.45359237) + " " + (float)(len /  0.0254) );
    }
}


2.1.3. 奇数求和

  • 思路:

    个人认为是想让我们设置一个数组记录所有数字,然后遍历数组求奇数和,可以不断赋值给同一个值,然后判断就行

  • 实现:

//奇数求和
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int tmp, ans=0;

        for (int i=1;i<=10;i++){
            tmp = sc.nextInt();
            if( (tmp & 1) == 1){
                ans += tmp;
            }
        }

        System.out.println(ans);
    }
}


2.1.4. 房产税费计算2022

  • 思路:

    个人认为读懂题意就行

  • 实现:

//房产税费计算2022
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int cnt = sc.nextInt();
        int value = sc.nextInt();
        int g = sc.nextInt();
        float s = sc.nextFloat();

        double a=0, b=0 ,c=0 ,d=0;

        if(cnt == 1){
            if(s <= 90) a = g * 0.01;
            else if(s <= 144) a = g * 0.015;
            else a = g * 0.03;
            
        }
        else {
            a = g * 0.03;
        }
        a *= 10000;
        
        b = value * 0.0005 * 10000;
        c = s * 3;
        d = s * 1.36;

		//注意转换为float类型即可
        System.out.println((float)a+" "+(float)b+" "+(float)c+" "+(float)d);
    }
    
}

2.1.5. 游戏角色选择

  • 思路:

    设置两个数组预存要选择的种族和职业,之后取出即可

  • 实现:

//游戏角色选择
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String[] arr_1 = new String[] {"人类","精灵","兽人","暗精灵"};
        String[] arr_2 = new String[] {"战士","法师","射手"};
        int a, b;

        a = sc.nextInt();
        b = sc.nextInt();

		//check
        if( (a<1) || (a>4) || (b<1) || (b>3) ){
            System.out.println("Wrong Format");
            return;
        }
        //注意数组下标0开始
        System.out.println(arr_1[a-1] + " " + arr_2[b-1]);

    }

}

2.1.6.学号识别

  • 思路:

    设置一个数组预存学院,因为学院编号只有01, 02,03, 20,可以观察出编号末尾不相同,因此可以以此作为数组索引;
    判断学号是否合法可采用Strng的内置API实现,关于这些移步: java String类(超详细!)
    输出采用printf格式化输出

  • 实现:

//学号识别
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String str = sc.nextLine();

        if(!check(str)){
            System.out.println("Wrong Format");
            return ;
        }

        String[] tmp = new String[]{"软件","材料","机械","外语"};


        System.out.printf(
            "入学年份:20%s年\n" +
            "学院:%s学院\n" +
            "班级:%s\n" +
            "学号:%s"
            ,str.substring(0,2),tmp[str.charAt(3)-'0']
            ,str.substring(4,6),str.substring(6,8)
        );

    }

    public static boolean check(String str){
        if(str.length() != 8) return false;
        if( str.substring(2,4).compareTo("01") == 0 ) return true;
        if( str.substring(2,4).compareTo("02") == 0 ) return true;
        if( str.substring(2,4).compareTo("03") == 0 ) return true;
        if( str.substring(2,4).compareTo("20") == 0 ) return true;


        return false;
    }
}

2.1.7. 巴比伦法求平方根近似值

  • 思路:

    输入输出题

  • 实现:

//巴比伦法求平方根近似值
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        float n, lastGuess,nextGuess;
        n = sc.nextFloat();
        lastGuess = sc.nextFloat();

        if(lastGuess<=0 ||n<0){
            System.out.println("Wrong Format");
            return;
        }

        while(true){
            nextGuess = (float) ((lastGuess + n/lastGuess) / 2.0);
            if(Math.abs(nextGuess-lastGuess) >= 0.00001){
                lastGuess = nextGuess;
            }
            else break;

        }

        System.out.println(lastGuess+" ");
    }

}

2.1.8. 二进制数值提取

  • 思路:

    如果是-1只会出现在末尾的话,那么这题就简单了,直接判断到String.length()-2即可;
    但是这题-1会出现在中间或者不出现,那么就是典型子串在主串的第一次出现位置,可以双重循环暴力找,也可以利用 kmp 寻找,再或者利用Stirng内置API自己构造一个这样的函数
    kmp请移步:

  • 实现:

//二进制数值提取
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String tmp;
        char[] st = new char[1000];
        int top = 0;

        tmp = sc.nextLine();

        int pos = findStr(tmp,"-1");
        if(pos == -1){
            System.out.println("Wrong Format");
            return;
        }

        for(int i=0;i<pos;i++){
            if (tmp.charAt(i)=='0' || tmp.charAt(i)=='1'){
                st[top++] = tmp.charAt(i);
            }
        }

        System.out.println(st);


    }
    //子串位置
    public static int findStr(String s1, String s2){
        int L = s2.length();
        int n = s1.length();
        for(int start = 0;start<n-L+1;start++){
            if(s1.substring(start,start+L).equals(s2)){
                return start;
            }
        }
        return -1;
    }
}


2.1.9. 判断三角形类型

  • 思路:

    对三个边按大小升序设置为a < b < c,非法数据则一定有(a+b)<= c;
    等边三角形有a = b = c ;
    等腰三角形有a = b || b = c;
    直角三角形有: pow(a,2) + pow(b,2) = pow(c,2);

  • 实现:

//判断三角形类型
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double[] arr = new double[3];
        boolean flag = false;

		//输入数据并升序处理
        for(int i=0;i<3;i++){
            arr[i] = sc.nextDouble();
            if (arr[i]<1 || arr[i]> 200) flag = true;
        }
        Arrays.sort(arr);

		//flag检测数据是否在合法范围内
        if (flag){
            System.out.println("Wrong Format");
            return;
        }
        
        //无法构成三角形
        if(arr[0] + arr[1] <= arr[2]){
            System.out.println("Not a triangle");
            return;
        }
        //等边三角形
        if(arr[0]==arr[1]&&arr[1]==arr[2]){
            System.out.println("Equilateral triangle");
            return;
        }

		//right判断是否为直角三角形,isosceles判断是否为等腰三角形
        boolean right = false, isosceles = false;
        //请看注意点
        if(Math.abs( Math.pow(arr[0],2) + Math.pow(arr[1],2) - Math.pow(arr[2],2)) <0.0000001 ) right = true;
        if(arr[0]==arr[1] || arr[1]==arr[2]) isosceles = true;

		//等腰直角三角形
        if(right && isosceles){
            System.out.println("Isosceles right-angled triangle");
            return;
        }
        //直角三角形
        if (right){
            System.out.println("Right-angled triangle");
            return;
        }
        //等边三角形
        if (isosceles){
            System.out.println("Isosceles triangle");
            return;
        }
        //一般路过普通三角形
        System.out.println("General triangle");

    }

}

复杂度分析

为简洁起见,本次练习只针对最后一题进行复杂度分析:

image-20220929220053009

由于是第一次练习,也是我只是为了过题,并没有把判断拆分成一个一个函数,导致圈复杂度V(G)过高



2.2. practice 2

2.2.1. 字母-数字转换

  • 思路:

    循环遍历str判断是否合法;
    利用String.toLowerCase()转字符为小写,或者利用String.toUpperCase()转大写;
    利用String.charAt() - ‘a’ + 1转数字(转大写则为String.charAt() - ‘A’ + 1)

  • 实现:

//字母-数字转换
import java.util.*;

public class Main{

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str;

        str = sc.nextLine();
        
        //check
        for(int i=0;i<str.length();i++){
            if(str.charAt(i)<'A' || str.charAt(i)>'z'){
                System.out.println("Wrong Format");
                return;
            }
        }

		//转化为小写
        str = str.toLowerCase();

		//转数字
        for(int i=0;i<str.length();i++){
            System.out.printf("%d",str.charAt(i)-'a'+1);
        }
    }
}

2.2.2. 串口字符解析

  • 思路:

    一个信号由起始位(1),数据位(8),奇偶判断位(1),结束位(1)共 11 位组成;

    当位数不足11时,不足以一个信号,特判结束;
    设置一个ok代表有无信号出现,在结束时特判;
    先判断结束位是否为1,在判断奇偶位的正确性(注意:当数据位1的个数为奇数时,奇偶位为0,反之则为1);
    以上均满足则输出数据;

  • 实现:

//串口字符解析
import java.util.*;

public class Main{

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str;
        int pos=0, cnt=0;
        boolean ok = false;

        str = sc.nextLine();
        int len = str.length();

        if(len < 11){
            System.out.println("null data");
            return ;
        }    //位数不足一个信号

        while(pos < len){
            if(str.charAt(pos) == '0'){	//0为信号的起始位
                ok = true;
                if( pos+11 > len){
                    return;
                }   //位数不足一个信号

                if( str.charAt(pos+10) != '1' ){
                    System.out.printf("%d:validate error\n",++cnt);
                }   //最后一位不是1(优先级高于奇偶校验)

                else if( cnt_chart_1(str.substring(pos+1,pos+9)) != (str.charAt(pos+9)-'0') ){
                    System.out.printf("%d:parity check error\n",++cnt);
                }   //奇偶校验失败

                else {
                    System.out.printf("%d:%s\n",++cnt,str.substring(pos+1,pos+9));
                }   //有效信号

                pos += 11;
            }
            pos++;
        }
        
        
        if(!ok){
            System.out.printf("null data\n");
        }	//没有信号,即全部是1的情况
    }

	//信号的奇偶检验
    public static int cnt_chart_1(String str){
        int res = 0;
        for(int i=0;i<str.length();i++){
            if(str.charAt(i) == '1') res++;
        }
        return 1^(res&1);
    }

}

2.2.3. String的格式判断与内容提取

  • 思路:

    特判掉输入字符串长度小于8的样例;

    1. 学生为17,18,19,20届软件学院人员,所以学号前四位在(2020,1920,1820,1720)中;
    2. 只要有一个学号不合法直接结束程序;
  • 实现:

//null
import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] sno = new String[1000];
        String str =sc.nextLine();
        int cnt=0;

        int len = str.length(), pos=0;

        if(len<8){
            System.out.print("Wrong Format");
            return;
        }

        while (pos < len){
            if(!check(str.substring(pos,pos+8))){
                System.out.print("Wrong Format");
                return;
            }

            if(ok(str.substring(pos,pos+8)))
                sno[cnt++] = str.substring(pos+4,pos+8);
            pos+=8;

        }

        for (int i=0;i<cnt;i++){
            System.out.printf("%s",sno[i]);
            if(i!=cnt-1)System.out.print(" ");
        }
        

    }

    public static boolean check(String str){
//        System.out.println("debug"+str);
        for(int i=0;i<str.length();i++){
            if(str.charAt(i)<'0' || str.charAt(i)>'9') return false;
        }
        return str.startsWith("2020") || str.startsWith("1920") || str.startsWith("1820") || str.startsWith("1720");
    }
    
    public static boolean ok(String str){
        return str.startsWith("202017") || str.startsWith("202061") ;
    }

}

复杂度分析

​ 为简洁起见,本次练习只分析第二题:

image-20220929221536406

程序圈复杂度在可接受范围之内



2.3. practice 3

2.3.1. 点线形系列1-计算两点之间的距离

  • 思路:

    1. 采用String.split函数将输入串分割;(将会生成一个tmpstr数组),其中数组长度代表值的个数(不合法输出“wrong number of points”)

    2. 采用正则表达式对数组中的每一个进行判断,有不满足的就输出“Wrong format”

    3. 采用Double.parsedouble函数将数组中的每一个转换为double型的num数组

    4. 将num数组中的值赋值给Point型的p数组

    5. 调用Point.disToPoint即可

  • 实现:

package nchu_software_oop_2022_3;

import java.util.*;
import Points.*;

public class p_1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();

        //将串转化为浮点型
        String[] tmpstr = str.split(" |,");
        double[] num = new double[30];
        int cnt = 0;
        for (String a : tmpstr) {
            if (!check(a)) {
                System.out.println("Wrong Format");
                return;
            }
            num[cnt++] = Double.parseDouble(a);
        }

        //将浮点型转化为坐标点型
        Point[] p = new Point[10];
        for (int i = 0; i < cnt; i += 2) {
            p[i / 2] = new Point(num[i], num[i + 1]);
        }

        //特判
        if(cnt != 4){
            System.out.println("wrong number of points");
            return;
        }
        //ans
        System.out.println(p[0].disToPoint(p[1]));

    }

    public static boolean check(String str){
        return str.matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$");
    }


}

2.3.2. 点线形系列2-线的计算

  • 思路:

    1. 前4点和第一题一致,只不过加了一个正则表达式;
      (以下不在赘述非法情况)

    2. cmd == 1: 调用Point.Slope函数,特判返回值为2^48(斜率无穷大)的情况

    3. cmd == 2:调用Point.dis函数

    4. cmd == 3:调用Point.inLine函数

    5. cmd == 4:调用Line.isCrawlTo函数

    6. cmd == 5:先调用Line.isCrawlTo函数特判平行,在调用Line.getIntersection函数获取两线段交点,再调用Line.inLineSegment函数判断交点是否在两条线段的任一条内

  • 实现:

package nchu_software_oop_2022_3;

import java.util.*;
import Points.*;

public class p_2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();

        //判断输入格式是否正确
        if(!str.matches("^[1-5][:](([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))[,]([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))\\s?)+$")){
            System.out.println("Wrong Format");
            return;
        }

        //取出cmd,将串转化为浮点型
        int cmd = str.charAt(0)-'0';
        str = str.substring(2).trim();
        String[] tmpstr = str.split(" |,");
        double[] num = new double[30];
        int cnt = 0;
        for(String aa:tmpstr){
            if(!check(aa)){
                System.out.println("Wrong Format");
                return;
            }
            num[cnt++] = Double.parseDouble(aa);
        }

        //将浮点型转化为坐标点型
        Point[] p = new Point[10];
        for(int i=0;i<cnt;i+=2){
            p[i/2] = new Point(num[i],num[i+1]);
        }

        //特判(判断掉那些点数非法的输入)
        if(cmd==1){
            if(cnt != 4){
                System.out.println("wrong number of points");
                return ;
            }
        }
        if(cmd==2 || cmd==3){
            if(cnt!=6){
                System.out.println("wrong number of points");
                return ;
            }
        }
        if(cmd==4 || cmd==5){
            if(cnt!=8){
                System.out.println("wrong number of points");
                return ;
            }
        }

        //题目要求(无脑if)
        if(cmd==1){
        	//坐标点重合
            if(p[0].isSameTo(p[1])){
                System.out.println("points coincide");
                return ;
            }
            Line l = new Line(p[0],p[1]);
            //l.b为0说明直线没有斜率
            if(Math.abs(l.b) <=0.0001){
                System.out.println("Slope does not exist");
                return;
            }
            System.out.println(p[0].Slope(p[1]));
        }

        if(cmd==2){
            if(p[1].isSameTo(p[2])){
                System.out.println("points coincide");
                return ;
            }
            Line l = new Line(p[1],p[2]);
            System.out.println(p[0].dis(l));
        }

        if(cmd==3){
            if(p[1].isSameTo(p[2])){
                System.out.println("points coincide");
                return ;
            }
            System.out.println(p[0].inLine(p[1],p[2]));

        }
        if(cmd==4){
            if(p[0].isSameTo(p[1]) || p[2].isSameTo(p[3])){
                System.out.println("points coincide");
                return ;
            }
            Line l1 = new Line(p[0],p[1]);
            Line l2 = new Line(p[2],p[3]);

            System.out.println(l1.isCrawlTo(l2));

        }
        if(cmd==5){
            if(p[0].isSameTo(p[1]) || p[2].isSameTo(p[3])){
                System.out.println("points coincide");
                return ;
            }
            Line l1 = new Line(p[0],p[1]);
            Line l2 = new Line(p[2],p[3]);

			//特判平行
            if(l1.isCrawlTo(l2)){
                System.out.println("is parallel lines,have no intersection point");
                return ;
            }
            Point tmp = l1.getIntersection(l2);	//交点坐标
            //注意是 或
            boolean t = l2.inLineSegment(tmp)||l1.inLineSegment(tmp);	//交点在任一线段之内
            System.out.println(tmp.x+","+tmp.y+" "+t);

        }

    }
	//正则表达式判断输入合法性
    public static boolean check(String str){
//        System.out.println("debug"+str);
        return str.matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$");
    }
}


2.3.3. 点线形系列3-三角形的计算

  • 思路:

    1. 前几点和前两题差不多,相当于初始化操作

    2. cmd == 1:调用Triangle.isIsoscelesTriangle函数 和 Triangle.isEquilateralTriangle函数即可

    3. cmd == 2:调用三角形类里面求周长,面积,周长的函数即可

    4. cmd == 3:调用Triangle.type函数即可

    5. cmd == 4:

      1. 先调用Line.isSameTo函数特判直线与三角形任一边重合的情况

      2. 求出直线与三条边各自的交点,并求出交点是否各自位于对应的边内(Boolean)(不包括端点);

      3. 特判直线交于三角形任一角的情况(like this):

      4. 以上完毕之后,只剩下交点为2个和0个的情况(like this):

    6. cmd == 5:调用Triangle.isContainPoint函数即可

  • 实现:

package nchu_software_oop_2022_3;

import java.util.*;
import Points.*;


public class p_3 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();

        //判断输入格式是否正确
        if(!str.matches("^[1-5][:](([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))[,]([+-]?(0|(0\\.\\d+)|[1-9][0-9]*(\\.\\d+)?))\\s?)+$")){
            System.out.println("Wrong Format");
            return;
        }

        //取出cmd,将串转化为浮点型
        int cmd = str.charAt(0)-'0';
        str = str.substring(2).trim();
        String[] tmpstr = str.split(" |,");
        double[] num = new double[30];
        int cnt = 0;
        for(String a:tmpstr){
            if(!check(a)){
                System.out.println("Wrong Format");
                return;
            }
            num[cnt++] = Double.parseDouble(a);
        }

        //将浮点型转化为坐标点型
        Point[] p = new Point[10];
        for(int i=0;i<cnt;i+=2){
            p[i/2] = new Point(num[i],num[i+1]);
        }

        //特判(坐标点数量非法)
        if(cmd==1|| cmd==2 || cmd==3){
            if(cnt != 6){
                System.out.println("wrong number of points");
                return;
            }
            Triangle t = new Triangle(p[0],p[1],p[2]);
            if(t.area() == 0){
                System.out.println("data error");
                return;
            }
        }
        if(cmd==4){
            if(cnt != 10){
                System.out.println("wrong number of points");
                return;
            }
            Triangle t = new Triangle(p[2],p[3],p[4]);
            if(t.area() == 0){
                System.out.println("data error");
                return;
            }
            if(p[0].isSameTo(p[1])){
                System.out.println("points coincide");
                return;
            }
        }
        if(cmd==5){
            if(cnt != 8){
                System.out.println("wrong number of points");
                return;
            }
            Triangle t = new Triangle(p[1],p[2],p[3]);
            if(t.area() <= 0.01){
                System.out.println("data error");
                return;
            }
        }
        

        //题目要求
        if(cmd == 1){
            Triangle t = new Triangle(p[0],p[1],p[2]);
            System.out.printf("%s %s\n",t.isIsoscelesTriangle(),t.isEquilateralTriangle());
        }
        if (cmd == 2){

            Triangle t = new Triangle(p[0],p[1],p[2]);
            System.out.printf("%s %s %s,%s\n",cnm(t.sideLength()),cnm(t.area()),cnm(t.focusPoint().x),cnm(t.focusPoint().y));
        }
        if (cmd == 3){
            Triangle t = new Triangle(p[0],p[1],p[2]);
            System.out.printf("%s %s %s",t.type()==2,t.type()==1,t.type()==0);
        }
        if (cmd == 4){
            Line l = new Line(p[0],p[1]);
            Triangle t = new Triangle(p[2],p[3],p[4]);
            //与任意一条边重合
            if(l.isSameTo(t.ab) || l.isSameTo(t.ac) || l.isSameTo(t.bc)){
                System.out.println("The point is on the edge of the triangle");
                return;
            }
            //与三条边的交点(值可能为null,即平行)
            Point p_ab = l.getIntersection(t.ab);
            Point p_ac = l.getIntersection(t.ac);
            Point p_bc = l.getIntersection(t.bc);

            //三交点是否位于边之内
            boolean p_ab_in=false, p_ac_in =false, p_bc_in=false;
            if(p_ab != null)  p_ab_in = t.ab.inLineSegment(p_ab);
            if(p_ac != null)  p_ac_in = t.ac.inLineSegment(p_ac);
            if(p_bc != null)  p_bc_in = t.bc.inLineSegment(p_bc);



            //任一角在直线之上(特判三角形的角)
            if(l.inLine(t.a)){
                //与另一条边无交点或者交点在边之外
                if(p_bc == null || !t.bc.inLineSegment_close(p_bc)){
                    System.out.println("1");
                }
                else pr_ans(t,t.a,t.b,p_bc);
                return;
            }
            if(l.inLine(t.b)){
                if(p_ac == null || !t.ac.inLineSegment_close(p_ac)){
                    System.out.println("1");
                }
                else pr_ans(t,t.a,t.b,p_ac);
                return;
            }
            if(l.inLine(t.c)){
                if(p_ab == null || !t.ab.inLineSegment_close(p_ab)){
                    System.out.println("1");
                }
                else pr_ans(t,t.a,t.c,p_ab);
                return;
            }

            //两个交点
            if(p_ab_in && p_bc_in){ pr_ans(t,t.b,p_ab,p_bc);return;}
            if(p_ab_in && p_ac_in){ pr_ans(t,t.a,p_ab,p_ac);return;}
            if(p_bc_in && p_ac_in){ pr_ans(t,t.c,p_bc,p_ac);return;}
            //无交点
            System.out.println("0");
        }
        
        if (cmd == 5){
            Triangle t = new Triangle(p[1],p[2],p[3]);
            int v = t.isContainPoint(p[0]);
            if(v == 0) System.out.println("in the triangle");
            if(v == 1) System.out.println("on the triangle");
            if(v == 2) System.out.println("outof the triangle");
        }
    }
    public static boolean check(String str){
//        System.out.println("debug"+str);
        return str.matches("^[+-]?(0|(0\\.\\d+)?|[1-9][0-9]*(\\.\\d+)?)$");
    }
    public static void pr_ans(Triangle t, Point a,Point b,Point c){
        Triangle tmp_t =new Triangle(a,b,c);
        double[] ans = new double[2];
        ans[0] = tmp_t.area();
        ans[1] = t.area() - tmp_t.area();
        Arrays.sort(ans);

        System.out.printf("2 %s %s\n",cnm(ans[0]),cnm(ans[1]));
    }

    public static String cnm(double a){
        String res = String.format("%.6f",a);
        res = res.replaceAll("0+?$", "");
        if(res.charAt(res.length()-1) == '.') res+='0';
        return res;
    }
}


复杂度分析

第一题:

image-20220929223726925

       ok

第二题:

image-20220929223804609

       主函数复杂度较高

第三题:

image-20220929223852943

       主函数复杂度较高

3. 踩坑心得

  1. 第一次作业中有许多题,必须采用foat类型,不然会错,因为double类型精度更高,PTA测试点为文本对比,之后一模一样才正确;
    连古巴比伦都知道两个数相差小时可以看成近似相等,PTA为啥不行呢(恼
  2. 在定义线段类时,使用点斜式会造成精度丢失,应该使用一般式Ax + By + C = 0

4. 改进建议

       对第二次作业我认为我函数内的代码行数还是太长,而且不是很清晰明了,希望自己以后条件判断还是多用switch case的条件语句,少用if else语句,让自己的代码变得更可读一些。类似的性质也可以做成类函数,就不会让代码那么长一串,用相应的英文函数名表示就明白多了。
       对第三次作业我认为我需要去更多的了解类的设计和有关正则的方式。我在最后一题使用的合法性判断很杂是混合在各个功能中的,这样不仅大程度的提高了代码的复杂度而且可读性很低,大概只有我自己能弄的清楚的程度。老师在课上介绍了正则的方法去限定合法性,我还需要对其更深的了解直到能够熟练运用。具体要做的改进首先是用正则的方法写合法测试,再将多次项的分类作为一个类,此类中含整数项判断函数、一次项判断函数和多次项判断函数,主函数在进行筛选时就可以直接调用类中的函数,这样可以大幅的的减少重复代码,减少查重降低复杂度。

5. 总结

关于java中的数组

       java中的数组属于定长数组,定义时需要给定数组长度,这使得面对动态增删时不太方便,一是使用提供的copy函数复制出一个新的数组使用,2是额外设置一个arr.length自定义数组长度。

关于java中String类的API

       String作为经常使用的非一般类数据类型,内置API相当之多,但学习起来并不会太难,有时候只需要一个函数就能解决许多复杂的操作,使得代码更加简洁。

关于java中的类

       java中的类不同于c++,c++类允许自定义运算符,而java不行,因为java认为自定义运算符不够面对对象并且会使得运算符运用更加复杂增加程序员的学习成本,但是可以通过类中方法实现运算符的功能,需要时调用即可。

       若类中存在非一般类数据类型的数组,需要在析构函数中为其申请空间,否则将会出现非法访问的情况。

       类中的函数允许同名但是传入参数的不同的情况,使得“同一个函数”可以具有多个功能。

posted @ 2022-09-29 15:13  LasterCN  阅读(63)  评论(0)    收藏  举报