1. 문제

당구 연습



2. 개요

m x n 크기의 당구대가 있다.

특정한 시작점에서 여러 위치에 놓인 목적구들을 모두 원쿠션으로 맞추려고 한다.

공이 벽면에 닿으면 반사각은 항상 입사각과 같으며, 모서리에 정확히 맞은 경우 그 반대로 되돌아온다.

목적구들의 위치가 주어졌을 때, 주어진 시작점에서 목적구들까지의 최소 이동 거리를 구하는 문제.



3. 풀이 및 코드

3-1. 풀이

시작점에서 각 목적구를 당구대 각 변을 기준으로 대칭시킨 위치들 중 가장 짧은 거리가 문제에서 요구하는 최소 거리가 된다.

한 케이스마다 상하좌우 4개 변을 기준으로 대칭시킨 4곳과의 거리를 구해야 한다.

4개의 거리를 먼저 최댓값으로 초기화 한 후, 거리를 계산한다.

이 때, 치는 공의 이동 방향에 목적구가 위치하는 경우가 있으므로 각각 예외처리를 해 준다.

4곳과의 거리들 중 최솟값을 리턴하여 리스트에 저장하고, 모든 케이스 계산이 끝났다면 배열로 바꾸어 리턴한다.

3-2. C#

using System;
using System.Collections.Generic;

public class Solution {
    public int[] solution(int m, int n, int startX, int startY, int[,] balls) 
    {
        List<int> answer = new List<int>();

        int ballsCnt = balls.GetLength(0);

        for (int i = 0; i < ballsCnt; i++)
        {
            answer.Add(Calc_distance(m, n, startX, startY, balls[i, 0], balls[i, 1]));
        }

        return answer.ToArray();
    }

    static public int Calc_distance(int m, int n, int startX, int startY, int destX, int destY)
    {
        int result = 0;

        float dist1 = float.MaxValue;
        float dist2 = float.MaxValue;
        float dist3 = float.MaxValue;
        float dist4 = float.MaxValue;

        if (startY != destY || startX < destX)
            dist1 = MathF.Pow(startX - -destX, 2) + MathF.Pow(startY - destY, 2);
        if (startY != destY || startX > destX)
            dist2 = MathF.Pow(startX - (m * 2 - destX), 2) + MathF.Pow(startY - destY, 2);
        if (startX != destX || startY < destY)
            dist3 = MathF.Pow(startX - destX, 2) + MathF.Pow(startY - -destY, 2);
        if (startX != destX || startY > destY)
            dist4 = MathF.Pow(startX - destX, 2) + MathF.Pow(startY - (n * 2 - destY), 2);

        result = (int)MathF.Min(MathF.Min(MathF.Min(dist1, dist2), dist3),dist4);

        return result;
    }
}

Comments