나를 기록하다
article thumbnail
반응형

백준(baekjoon) 1485 정사각형

https://www.acmicpc.net/problem/1485

 

1485번: 정사각형

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 네 줄로 이루어져 있으며, 점의 좌표가 한 줄에 하나씩 주어진다. 점의 좌표는 -100,000보다 크거나 같고, 100,000보다 작거나 같

www.acmicpc.net

네 점이 주어졌을 때, 네 점을 이용해 정사각형을 만들 수 있는지 없는지를 구하는 프로그램을 작성하시오.

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 네 줄로 이루어져 있으며, 점의 좌표가 한 줄에 하나씩 주어진다. 점의 좌표는 -100,000보다 크거나 같고, 100,000보다 작거나 같은 정수이다. 같은 점이 두 번 이상 주어지지 않는다.

각 테스트 케이스마다 입력으로 주어진 네 점을 이용해서 정사각형을 만들 수 있으면 1을, 없으면 0을 출력한다.

 

4. 문제풀이

이번 문제는 로직을 짜서 정답을 맞추는데는 성공했다. 하지만 나의 첫 풀이에서 볼 수 있듯이, 코드가 매우 난잡하고, 자바의 장점인 객체 지향성을 전혀 살리지 못했다. 그저 돌아가기만 하는 코드다. 아직까지 객체지향적인 사고가 많이 부족한 듯하다.

우선 문제를 풀기 전에 어떻게 풀 지 정리를 했다.

내가 세운 정사각형의 규칙은 다음과 같다.

1. 네 변의 길이가 같을 것
2. 두 변이 이루는 각이 직각일 것

이런 규칙을 만족시키기 위해 다음과 같이 진행했다.

1. Point 클래스를 구현하여 입력받은 좌표 저장 
2. ArrayList<Point> pointList 구현
3. Comparator를 상속받은 PointComparator을 구현하여 x좌표 내림차순, y좌표 내림차순 정렬
4. 각 점의 좌표 추출 후, 점 간의 거리 제곱을 계산(powD01, powD02 ...)
5. isRectangle의 boolean형을 선언하여 직사각형인지 확인(대각선의 제곱 = 나머지 두 변의 각각의 제곱 합이 true인지 확인)
6. isRectangle = true이고, 4번에서 구한 네 변의 길이가 같으면 1을 출력, 아닐 경우 0을 출력
7. 다음 테스트 케이스를 위해 pointList 초기화

4.1. 첫번째 풀이

<java />
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.StringTokenizer; public class Main { public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); int testCaseCount = Integer.parseInt(reader.readLine()); // 테스트 케이스 진행 횟수 ArrayList<Point> pointsList = new ArrayList<>(); // points 리스트를 반복문 밖에서 선언 for (int i = 0; i < testCaseCount; i++) { // 한 테스트 케이스마다 4개의 점 정보 입력 for (int j = 0; j < 4; j++) { StringTokenizer tokenizer = new StringTokenizer(reader.readLine()); int x = Integer.parseInt(tokenizer.nextToken()); int y = Integer.parseInt(tokenizer.nextToken()); pointsList.add(new Point(x, y)); } pointsList.sort(new PointComparator()); // 정렬 기준을 활용하여 내림차순 정렬 // 각 점의 좌표 추출 int x0 = pointsList.get(0).x; int x1 = pointsList.get(1).x; int x2 = pointsList.get(2).x; int x3 = pointsList.get(3).x; int y0 = pointsList.get(0).y; int y1 = pointsList.get(1).y; int y2 = pointsList.get(2).y; int y3 = pointsList.get(3).y; // 점 간의 거리 제곱 계산 int powD01 = (int) (Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2)); int powD02 = (int) (Math.pow(x0 - x2, 2) + Math.pow(y0 - y2, 2)); int powD13 = (int) (Math.pow(x1 - x3, 2) + Math.pow(y1 - y3, 2)); int powD23 = (int) (Math.pow(x2 - x3, 2) + Math.pow(y2 - y3, 2)); int powD12 = (int) (Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); // 직사각형 여부 판단 boolean isRectangle = powD12 == powD01 + powD02; // 직사각형이면서 네 변의 길이가 모두 같은지 검사 if (isRectangle && (powD01 == powD02) && (powD02 == powD13) && (powD13 == powD23)) { System.out.println(1); // 직사각형이면서 네 변의 길이가 모두 같을 경우 } else { System.out.println(0); // 직사각형이 아닐 경우 } pointsList.clear(); // 다음 테스트 케이스를 위해 리스트 초기화 } } // 좌표를 저장하는 클래스 private static class Point { int x, y; Point(int x, int y) { this.x = x; this.y = y; } } // 점을 내림차순으로 정렬하기 위한 Comparator 구현 private static class PointComparator implements Comparator<Point> { @Override public int compare(Point p1, Point p2) { if (p1.x != p2.x) { return p2.x - p1.x; } else { return p2.y - p1.y; } } } }

 

4.2. 두번째 풀이

두번째 풀이는 다른 사람들의 코드를 보면서 참고하다가 가장 객체지향적인 코드를 조금만 다듬어서 올렸다. 자바를 사용할 때는 이렇게 객체지향적으로 생각하고 코드를 작성해야겠다는 것을 다시 한 번 느낄 수 있는 코드였다.

<java />
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; public class Main { public static void main(String[] args) throws IOException { new Main().solve(); } // 좌표를 나타내는 클래스 class Position { int x, y; // 좌표 생성자 public Position(int x, int y) { this.x = x; this.y = y; } } // 두 좌표 사이의 거리 계산 메서드 private long calculateDistance(Position p1, Position p2) { return 1L * (p1.x - p2.x) * (p1.x - p2.x) + 1L * (p1.y - p2.y) * (p1.y - p2.y); } private void solve() throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int testCaseCount = Integer.parseInt(br.readLine()); // 테스트 케이스 개수 입력 StringBuilder sb = new StringBuilder(); // 각 테스트 케이스에 대하여 반복 while (testCaseCount-- > 0) { Position[] positions = new Position[4]; // 4개의 좌표를 저장할 배열 생성 // 4개의 좌표 정보 입력 for (int i = 0; i < 4; i++) { String[] input = br.readLine().split(" "); positions[i] = new Position(Integer.parseInt(input[0]), Integer.parseInt(input[1])); } long[] distances = new long[6]; // 거리를 저장할 배열 생성 int idx = 0; // 모든 좌표 쌍에 대해 거리 계산 후 배열에 저장 for (int i = 0; i < 4; i++) { for (int j = i + 1; j < 4; j++) { distances[idx++] = calculateDistance(positions[i], positions[j]); } } Arrays.sort(distances); // 거리 배열을 오름차순으로 정렬 // 모든 거리가 같은 경우 직사각형이므로 1, 아닌 경우 0을 결과에 추가 if (distances[0] == distances[1] && distances[1] == distances[2] && distances[2] == distances[3] && distances[4] == distances[5]) { sb.append(1); } else { sb.append(0); } sb.append('\n'); // 개행문자 추가 } br.close(); // 입력 스트림 닫기 System.out.print(sb); // 결과 출력 } }

두번째 코드 출처

https://github.com/nahwasa/BOJ_BaekjoonOnlineJudge/blob/master/01400/BOJ_1485.java

 

반응형
profile

나를 기록하다

@prao

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!