- 두개의 공이 벽까지의 거리가 가장 짧은 벽을 선택
- 예외처리
- 가는 길에 공이 있을 경우(벽에 부딪치기 전에 공에 막힘) 다른 벽을 쿠션으로 사용한다.
- 두 공들의 벽까지 수직거리 구함
- 벽에 투영했을 때 공사이의 거리
- 투영한 거리를 수직거리의 비율로 나눔
- 피타고라스 정리로 거리 구함
public int[] solution(int m, int n, int startX, int startY, int[,] balls)
{
int[] answer = new int[] { };
int startXToLeft = startX;
int startXToRight = m - startX;
int startYToDown = startY;
int startYToUp = n - startY;
List<int> ans= new List<int>();
for (int i = 0; i < balls.GetLength(0); i++)
{
int destX = balls[i, 0];
int destY = balls[i, 1];
int destXToLeft = destX;
int destXToRight = m - destX;
int destYToDown = destY;
int destYToUp = n - destY;
bool isLeft;
bool isDown;
isLeft = startXToLeft + destXToLeft < startXToRight + destXToRight;
isDown = startYToDown + destYToDown < startYToUp + destYToUp;
int minX = Math.Min(startXToLeft + destXToLeft, startXToRight + destXToRight);
int minY = Math.Min(startYToDown + destYToDown, startYToUp + destYToUp);
int startHeight;
int destHeight;
int startWidth;
int destWidth;
// 1. 두개의 공이 벽까지의 거리가 가장 짧은 벽을 선택
if (minX < minY)
{
// 3. 두 공들의 벽까지 수직거리 구함
startHeight = isLeft ? startXToLeft : startXToRight;
destHeight = isLeft ? destXToLeft : destXToRight;
// 4. 벽에 투영했을 때 공사이의 거리
// 5. 투영한 거리를 수직거리의 비율로 나눔
startWidth = Math.Abs(startY - destY) * startHeight / (startHeight + destHeight);
destWidth = Math.Abs(startY - destY) * destHeight / (startHeight + destHeight);
}
else
{
startHeight = isDown ? startYToDown : startYToUp;
destHeight = isDown ? destYToDown : destYToUp;
startWidth = Math.Abs(startX - destX) * startHeight / (startHeight + destHeight);
destWidth = Math.Abs(startX - destX) * destHeight / (startHeight + destHeight);
}
// 예외처리
if (destX == startX)
{
startHeight = isLeft ? startXToLeft : startXToRight;
destHeight = isLeft ? destXToLeft : destXToRight;
startWidth = Math.Abs(startY - destY) * startHeight / (startHeight + destHeight);
destWidth = Math.Abs(startY - destY) * destHeight / (startHeight + destHeight);
}
else if (destY == startY)
{
// y값을 높이로 사용하는 삼각형을 만든다.
startHeight = isDown ? startYToDown : startYToUp;
destHeight = isDown ? destYToDown : destYToUp;
startWidth = Math.Abs(startX - destX) * startHeight / (startHeight + destHeight);
destWidth = Math.Abs(startX - destX) * destHeight / (startHeight + destHeight);
}
// 6. 피타고라스 정리로 거리 구함
double startToWall = Math.Sqrt(Math.Pow(startHeight, 2) + Math.Pow(startWidth, 2));
double destToWall = Math.Sqrt(Math.Pow(destHeight, 2) + Math.Pow(destWidth, 2));
double distance = startToWall + destToWall;
ans.Add((int)Math.Pow(distance,2));
}
answer = ans.ToArray();
return answer;
}
결과 : 실패
- 그림을 다시 보니 맞은 벽을 기준으로 이동한 길을 반전시키면 튕겨나온 길이 직선이 된다.
- 이렇게 해결하면 소수점을 계산할 필요도 없어진다.
- 가장 가까운 벽을 찾는다.
- 두 공이 벽까지의 거리를 합한다.
- 두 공을 벽에 투영했을때의 거리를 구한다.
- 피타고라스
public int[] solution(int m, int n, int startX, int startY, int[,] balls)
{
int[] answer = new int[] { };
int startXToLeft = startX;
int startXToRight = m - startX;
int startYToDown = startY;
int startYToUp = n - startY;
List<int> ansList= new List<int>();
for (int i = 0; i < balls.GetLength(0); i++)
{
int destX = balls[i, 0];
int destY = balls[i, 1];
int destXToLeft = destX;
int destXToRight = m - destX;
int destYToDown = destY;
int destYToUp = n - destY;
int minX = Math.Min(startXToLeft + destXToLeft, startXToRight + destXToRight);
int minY = Math.Min(startYToDown + destYToDown, startYToUp + destYToUp);
int height;
int width;
int ans;
// 예외처리
if (destX == startX)
{
height = minX;
width = Math.Abs(startY - destY);
ans = (int)Math.Pow(height,2) + (int)Math.Pow(width,2);
}
else if (destY == startY)
{
height = minY;
width = Math.Abs(startX - destX);
ans = (int)Math.Pow(height,2) + (int)Math.Pow(width,2);
}
else
{
height = minX;
width = Math.Abs(startY - destY);
int ans1 = (int)Math.Pow(height, 2) + (int)Math.Pow(width, 2);
height = minY;
width = Math.Abs(startX - destX);
int ans2 = (int)Math.Pow(height, 2) + (int)Math.Pow(width, 2);
ans = Math.Min(ans1, ans2);
}
ansList.Add(ans);
}
answer = ansList.ToArray();
return answer;
}
결과 : 실패
- 나는 두 번의 풀이를 할 때 정사각형의 판만 주어진다고 생각하고 풀이를 하고 있었다. 그래서 x나 y가 같은 경우에 한쪽 방향만 제외하고 비교해야 하는데 양쪽 방향을 모두 제외했다.
- 그래서 모든 방향의 가능성을 거리를 모두 구하고 최소값을 찾는 방법을 선택했다.
- 상하좌우벽에 맞았을 때 거리를 구한다.
- 예외처리를 하고 최소값을 구한다.
public int[] solution(int m, int n, int startX, int startY, int[,] balls)
{
int[] answer = new int[] { };
int startXToLeft = startX;
int startXToRight = m - startX;
int startYToDown = startY;
int startYToUp = n - startY;
List<int> ansList= new List<int>();
for (int i = 0; i < balls.GetLength(0); i++)
{
int destX = balls[i, 0];
int destY = balls[i, 1];
int destXToLeft = destX;
int destXToRight = m - destX;
int destYToDown = destY;
int destYToUp = n - destY;
// 모든 방향의 거리
int left = (int)Math.Pow((startXToLeft + destXToLeft), 2) + (int)Math.Pow(startY - destY, 2);
int right = (int)Math.Pow((startXToRight + destXToRight), 2) + (int)Math.Pow(startY - destY, 2);
int down = (int)Math.Pow((startYToDown + destYToDown), 2) + (int)Math.Pow(startX - destX, 2);
int up = (int)Math.Pow((startYToUp + destYToUp), 2) + (int)Math.Pow(startX - destX, 2);
int ans;
// 예외처리
if (destX == startX)
{
if (destY > startY)
ans = Math.Min(Math.Min(left, right), down);
else
ans = Math.Min(Math.Min(left, right), up);
}
else if (destY == startY)
{
if (destX > startX)
ans = Math.Min(Math.Min(up, down), left);
else
ans = Math.Min(Math.Min(up, down), right);
}
else
{
ans = Math.Min(Math.Min(left, right), Math.Min( up, down));
}
ansList.Add(ans);
}
answer = ansList.ToArray();
return answer;
}