본문 바로가기

배운 거/Algorithm

백준 1064 평행사변형 JAVA

정답의 오차는 10의 -9승까지 허용이므로 float가 아닌 double로 값이 나가야한다.

이런 난이도의 문제는 처음이므로 많은 자료들을 확인했는데 일단 

코드는 아래 접은 글.

더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {

    private static class Coordinate {
        int x;
        int y;

        public Coordinate(int x, int y) {
            this.x = x;
            this.y = y;

        }

    }

    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Coordinate[] arr = new Coordinate[3]; // 클래스 배열 설정. 사용시 변수명으로 요소를 불러 올수있다.
        Double[] dist = new Double[3];
        StringTokenizer st = new StringTokenizer(br.readLine());
        for (int i = 0; i < 3; i++) {
            arr[i] = new Coordinate(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
            //클래스 arr 내부에 값 입력.
        }
        // (arr[1].y - arr[0].y)/(arr[2].x-arr[1].x)==(arr[2].y-arr[1].y)/(arr[2].x - arr[1].x)
        // 선분 AB의 기울기 == 선분 BC의 기울기
        // 평면내 주어진 좌표값이 같은 선에 일치하는 경우 확인
        // 분모가 0이 되어버리면 NAN 으로 반환하므로 이항식으로 아래와 같이 표현해야한다.
        if ((arr[1].y - arr[0].y) * (arr[2].x - arr[1].x) == (arr[2].y - arr[1].y) * (arr[1].x - arr[0].x)) {
            System.out.println(-1);

        }else {
            dist[0] = Math.sqrt(Math.pow(arr[0].x - arr[1].x, 2) + Math.pow(arr[1].y - arr[0].y, 2)) * 2; //AB * 2
            dist[1] = Math.sqrt(Math.pow(arr[1].x - arr[2].x, 2) + Math.pow(arr[2].y - arr[1].y, 2)) * 2; //BC * 2
            dist[2] = Math.sqrt(Math.pow(arr[2].x - arr[0].x, 2) + Math.pow(arr[2].y - arr[0].y, 2)) * 2; //AC * 2

            ArrayList<Double> answer = new ArrayList<>();
            answer.add(dist[0]+dist[1]);
            answer.add(dist[1]+dist[2]);
            answer.add(dist[2]+dist[0]);

            Double min = answer.stream().mapToDouble(value -> value).min().orElseThrow();
            Double max = answer.stream().mapToDouble(value -> value).max().orElseThrow();

            System.out.println(max - min);}


    }


}

입력값 처리 Scanner를 쓰는게 편하지만 BufferedReader가 입력처리가 빠르므로

BufferedReader로 입력값을 가져와서 클래스 배열의 좌표값으로 저장해둔다.

 

클래스 배열 사용시 변수명으로 요소를 호출할 수 있으므로 코드 작성하기 용이해진다.

Double 배열도 선언 해주었는데 나중에 계산해두고 간단한 수식을 통해 답을 출력하기 위해서다.

 

BufferdReader로 입력값을 가져오면 String 값으로 가져오게 되는데

split의 함수와 같은 역할이지만 속도가 더 빠르다.

 

위에 Coordinate 클래스 배열에 가져온 좌표값을 넣어주는데

좌표는 정수로 주어지는 조건이며 어차피 나중에 계산식을 통해 Double타입으로 parsing 될꺼니까

int 값으로 배열에 저장해준다.

 

예외조건을 보면 평행사변형을 만들 수 없을 때 -1 을 반환해야 하므로

평행사변형을 만들 수 없는 조건인 주어진 좌표의 세점이 한 직선안에 들어있을 경우를 수식으로 나타내어야하는데

한 점을 기준으로 선분의 기울기를 구해주면된다.

 

코드작성시 주어진 선분 AB와 선분 BC의 기울기를 비교하면 되는데 

위와 같은 동등비교식을 아래와 같이 나타냈을 때

(arr[1].y - arr[0].y)/(arr[2].x-arr[1].x)==(arr[2].y-arr[1].y)/(arr[2].x - arr[1].x)

분모가 0인 계산식이 되어 NAN 값으로 출력이 될 수 있으므로 이항식을 통해 아래와 같이 수정해준다.

(arr[1].y - arr[0].y) * (arr[2].x - arr[1].x) == (arr[2].y - arr[1].y) * (arr[1].x - arr[0].x)

 

이제 평행 사변형의 둘레를 구해줘야하는 데

 

그림을 통해 주어진 좌표로 이루어진 삼각형을 먼저 그리고

 

만들어질 평행사변형의 각 대변을 같은 색으로 나타 내었을 때 아래와 같은데

 

 

결국 평행사변형의 길이는 한변의 길이 * 2 + 다른 한변의 길이 * 2의 수식으로 나타낼 수있다.

 

이때 좌표와 좌표의 길이는 x 좌표 차이의 제곱 , y좌표 차이의 제곱을 더하고 이 값의 제곱근을 구하면 된다.

(킹타고라스의 정리)

 

Math함수를 통해 수식을 코드로 정리하면 아래와 같다.

dist[0] = Math.sqrt(Math.pow(arr[0].x - arr[1].x, 2) + Math.pow(arr[1].y - arr[0].y, 2)) * 2; //AB * 2

이렇게 정리한 값을 ArrayList로 배열로 만들어주고 요소로 지정해준다음

최대값과 최소값의 차이를 출력해줬다.

 

 

Scanner VS Buffer

 

Scanner는 입력을 읽는 과정에서 내부에서 정규 표현식 적용, 입력값 분할, 파싱 과정 등을 거치기 때문에 속도가 느립니다.

 

유효자리수에 따른 double float 사용구분

유효자릿수 가 뜻하는 것은 정밀도 를 뜻합니다. 즉, 몇자리 까지 오차없이 표현할 수 있는가입니다. float은 7자리, double은 15~16자리 까지 표현할 수 있습니다. 따라서 float 의 정밀도보다 더 높은 정밀도가 필요하다면 double 을 사용해야 합니다.


reference

https://velog.io/@alicesykim95/Java-Class-Array-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%B0%B0%EC%97%B4

 

Java Class Array 클래스 배열

📌 1. 클래스 배열 생성 >클래스명[] 객체명 = new 클래스명[배열의 크기]; 📌 2. 생성자(Constructor) 📎 생성자란? > 코드를 짤 때 변수를 선언하면 반드시 초기화를 해주어야 한다. 초기화를 해주지

velog.io

https://mathbang.net/138

 

좌표평면에서 두 점 사이의 거리

이번에는 피타고라스의 정리를 도형이 아니라 좌표평면에서 활용해볼 거에요. 어려운 함수 나오는 거 아니니까 너무 걱정하지 마세요. 되게 쉬운 내용이에요. 거듭 얘기하지만, 피타고라스의

mathbang.net

https://restudycafe.tistory.com/296

 

[C언어 백준 풀이][Silver V] 1059번 : 좋은 구간 / 1064번 : 평행사변형 / 1094번 : 막대기

백준(Baekjoon Online Judge)의 Silver V 난이도의 1059번 : 좋은 구간, 1064번 : 평행사변형, 1094번 : 막대기를 풀이해보도록 하겠습니다. 1059번 : 좋은 구간 정수 집합 S에 대하여 n을 포함하고 정수 집합 S..

restudycafe.tistory.com

https://jhnyang.tistory.com/92

 

[Java 자바 입출력] BufferedReader/BufferedWriter

[자바 입출력 함수] BufferedReader / BufferWriter BufferedReader/BufferedWriter은 이름처럼 버퍼를 이용해서 읽고 쓰는 함수입니다. 이 함수는 버퍼를 이용하기 때문에 이 함수를 이용하면 입출력의 효율이..

jhnyang.tistory.com

https://www.youtube.com/watch?app=desktop&v=-GsrYvZoAdA

 

https://blog.naver.com/scyan2011/221656914043

 

[java]자바/Math/함수/pow, sqrt

Math.pow() 제곱 Math.pow(x, y)는 x의 y 제곱근을 반환하는 함수입니다. pow는 power의 약어로 수학에서...

blog.naver.com

https://houseofj.tistory.com/304

 

세 점이 일직선 위에 있을 조건

두 점을 지나는 직선의 기울기 구하기 두 점을 지나는 직선의 기울기를 구하기 위해서는 한 점을 기준으로 y의 증가량에 x의 증가량을 나누면 구할 수 있다. 이것을 공식처럼 나타내면 아래와 같

houseofj.tistory.com