개발 공부/코딩테스트 연습

[프로그래머스 Lv2][JAVA] 당구 연습

빵다희 2024. 9. 2. 22:36

❓문제설명

당구 연습

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


🔍 문제해석

어떤걸 풀어야 할까?

  • 시작공과 목표공이 있을때 시작공이 목표공의 위치로 도달하는 거리 중 최소값의 제곱을 구해라.
  • 시작공이 목표공 위치로 가기 위해서는 벽을 한번 부딪히는 원쿠션을 이용해야한다. 벽에 부딪힐 때, 입사각 반사각은 동일하다.

🧐 문제 풀이

이거 너무 어려운데 레벨2 맞나요ㅜㅜ

진짜 의욕 와장창 꺾인다.

하지만 카피라도 해서 익혀야지..ㅎㅎ 어떡해 뭐

참고 블로그 : https://ksb-dev.tistory.com/292

 

벽에 부딪힐 때, 입사각 반사각은 동일하는 걸 이용해서 시작 공의 이동 방향을 대칭적으로 구할 수 있다.

  • 첫 번째 방향: 물체가 벽에 부딪히기 전의 이동 방향.
  • 두 번째 방향: 벽에 부딪힌 후 반사된 방향.
  • 세 번째 방향: 첫 번째 방향의 반대편.
  • 네 번째 방향: 두 번째 방향에서 수직으로 반사된 방향.

(모르겠다..;;)

이렇게 구한 4가지의 대칭된 지점과 시작공의 거리를 계산해서 가장 짧은 거리를 구한다.

시작 공과 목표 공이 대칭적으로 위치해 있는 경우는 제외하고 방향을 계산해야 한다.

이 경우에는 벽에 부딪히기 전에 목표 공에 도달하기 때문이다.


! 제출코드

  1. 시작볼위치와 목표볼 위치를 이용해 시작공의 이동 방향의 대칭방향을 구한다.
  2. 그렇게 구한 대칭볼과과 시작볼의 거리 제곱을 구하고 가장 작은 값을 정답 배열에 담는다.
  3. 4개의 대칭 방향을 구하는 방법
  4. 두 볼 사이의 거리의 제곱을 구하는 방법
import java.util.*;
class Solution {
   public static int[] solution(int m, int n, int startX, int startY, int [][] balls) {

        // 답 배열
        int [] answer = new int[balls.length];

        // 당구대 범위
        Point board = new Point(m,n);

        // 시작 볼 위치
        Point start  = new Point(startX,startY);

        // 도착 볼 위치
        for(int i = 0; i < balls.length; i++){
            int [] ball = balls[i];
            
            // (1) 대칭 정보 반환
            List<Point> transBall = symmetricTransposition(board, start, new Point(ball[0], ball[1]));

            int minDistance = Integer.MAX_VALUE;
            for(Point point : transBall){
                // (2)대칭 볼들과 시작 볼의 거리 계산
                int distance = calculationDistance(start, point);
                
                // (2)가장 적은 거리를 담는다.
                minDistance = Math.min(minDistance, distance);
            }
            answer[i] = minDistance;
        }
        return answer;

    }

    // (3)
    private static List<Point> symmetricTransposition(Point board, Point start, Point ball){
        List<Point> syms = new ArrayList<>();

        // 4개의 방향으로 대칭이동
        // 선 대칭일 때, 벽보다 공에 먼저 맞는 경우 제외
        if(!(start.x == ball.x && start.y > ball.y)) syms.add(new Point(ball.x, ball.y * -1));
        if(!(start.x == ball.x && start.y < ball.y)) syms.add(new Point(ball.x, board.y + (board.y - ball.y)));
        if(!(start.x < ball.x && start.y == ball.y)) syms.add(new Point(board.x + (board.x - ball.x) , ball.y));
        if(!(start.x > ball.x && start.y == ball.y)) syms.add(new Point(ball.x * -1, ball.y));

        return syms;
    }
    
    // (4) 두 볼 사이간의 거리 제곱 계산
    private static int calculationDistance(Point start, Point ball){
        int deltaX = start.x - ball.x; // x 계산
        int deltaY = start.y - ball.y; // y 계산

        return deltaX * deltaX + deltaY * deltaY;
    }
    private static class Point {
        int x,y;
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}
728x90
반응형