문제 보기
https://www.acmicpc.net/problem/1002
정답 비율 22.279를 자랑하는 문제지만,
푸는 방법만 알고 있다면 그렇게 어렵진 않다.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 다음과 같이 이루어져 있다.
한 줄에 x1, y1, r1, x2, y2, r2가 주어진다. x1, y1, x2, y2는 -10,000보다 크거나 같고, 10,000보다 작거나 같은 정수이고, r1, r2는 10,000보다 작거나 같은 음이 아닌 정수이다.
우리에게 주어진 것은 조규현과 백승환의 좌표(x1, y1) (x2, y2) 그리고 류재명과의 거리 r1 r2이다.
사실 표현만 보더라도 푸는 방법을 유추해낼 수 있다.
r은 주로 원의 반지름(radius)을 표현할 때 쓰이기 때문이다.
이 문제는 원의 방정식을 사용하는 문제이다.
원의 방정식에 대한 자세한 설명은 아래 링크를 참조 바란다.
https://mathbang.net/454#gsc.tab=0
한 좌표를 기준으로 같은 거리에 위치한 점들을 연결하면 원을 그릴 수 있다.
류재명이 있을 수 있는 좌표란 결국
두 원이 만나는 점이라고 설명할 수 있다.
두 원의 교점이 존재한다면(두 곳에서 만난다면) 답은 2
두 원의 접점이 존재한다면(한 곳에서 만난다면) 답은 1
두 원이 만나지 않는다면 답은 0이다.
같은 평면 위에 두 원이 있을 때 두 원의 위치 관계는 6가지 경우가 있다.
아래 링크에서 자세한 설명을 볼 수 있다.
https://mathbang.net/101#gsc.tab=0
// 두 원이 완전히 같을 때
if (distanceA == distanceB && vector2A.x == vector2B.x && vector2A.y == vector2B.y)
{
print.WriteLine(-1);
}
// 반지름A와 반지름B의 합이 두 원의 중점의 거리보다 작을 때 (두 원이 만나지 않음)
else if (distanceA + distanceB < Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2))))
{
print.WriteLine(0);
}
// 반지름A와 반지름B의 합이 두 원의 중점의 거리와 같을 때 (두 원이 한 점에서 만남. 외접)
// 부동 소수점임을 감안하여 반올림
else if (distanceA + distanceB == Math.Round(Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2)))))
{
print.WriteLine(1);
}
// 반지름A와 반지름B의 합이 두 원의 중점의 거리보다 클 때
else if (distanceA + distanceB > Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2))))
{
// 반지름A와 반지름B의 차가 두 원의 중점의 거리보다 작을 때 (두 원이 두 점에서 만남. 교점)
if (Math.Abs(distanceA - distanceB) < Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2))))
{
print.WriteLine(2);
}
// 반지름A와 반지름B의 차가 두 원의 중점의 거리와 같을 때 (두 원이 한 점에서 만남. 내접)
else if (Math.Abs(distanceA - distanceB) == Math.Round(Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2)))))
{
print.WriteLine(1);
}
// 반지름A와 반지름B의 차가 두 원의 중점의 거리보다 클 때 (두 원이 만나지 않음)
else if(Math.Abs(distanceA - distanceB) > Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2))))
{
print.WriteLine(0);
}
}
본인은 6가지 경우의 수를 생각하여 분기를 두었다.
(더 깔끔하게 정리할 수 있는 방법이 있을 수도 있다.)
전체 코드
static void Main(string[] args)
{
using var reader = new System.IO.StreamReader(Console.OpenStandardInput());
using var print = new System.IO.StreamWriter(Console.OpenStandardOutput());
string input = reader.ReadLine();
int T = int.Parse(input);
for(int i = 0; i < T; i++)
{
input = reader.ReadLine();
(int x, int y) vector2A = (int.Parse(input.Split()[0]), int.Parse(input.Split()[1]));
int distanceA = int.Parse(input.Split()[2]);
(int x, int y) vector2B = (int.Parse(input.Split()[3]), int.Parse(input.Split()[4]));
int distanceB = int.Parse(input.Split()[5]);
if (distanceA == distanceB && vector2A.x == vector2B.x && vector2A.y == vector2B.y)
{
print.WriteLine(-1);
}
else if (distanceA + distanceB < Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2))))
{
print.WriteLine(0);
}
else if (distanceA + distanceB == Math.Round(Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2)))))
{
print.WriteLine(1);
}
else if (distanceA + distanceB > Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2))))
{
if (Math.Abs(distanceA - distanceB) < Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2))))
{
print.WriteLine(2);
}
else if (Math.Abs(distanceA - distanceB) == Math.Round(Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2)))))
{
print.WriteLine(1);
}
else if(Math.Abs(distanceA - distanceB) > Math.Sqrt(Math.Pow(vector2A.x - vector2B.x, 2) + (Math.Pow(vector2A.y - vector2B.y, 2))))
{
print.WriteLine(0);
}
}
}
}
'ProblemSolve' 카테고리의 다른 글
[백준][C#] 2407 조합 - 실버3 (0) | 2023.06.16 |
---|---|
[백준][C#] 1004 어린왕자 - 실버3 (0) | 2023.06.15 |
[백준][C#] 9375 패션왕 신해빈 - 실버3 (0) | 2023.06.14 |
[백준][C#] 9095 1, 2, 3 더하기 - 실버3 (1) | 2023.06.13 |
[백준][C#] 2579 계단 오르기 - 실버3 (0) | 2023.06.12 |