공부/백준

1002번: 터렛(백준 C++, 추가 테스트 케이스)

상연 2020. 10. 15. 18:04

 

 

1002번: 터렛 링크

코드

#include <iostream>
#include <math.h>
using namespace std;

int distance(int x1, int y1, int x2, int y2){
    return ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}

int main() {
    int t; // test case

    int x1, y1, r1; //조규현
    int x2, y2, r2; //백승환
    int dis, cnt;
    cin >> t;
    for(int i = 0; i < t; i++){
        cin >> x1 >> y1 >> r1 >> x2 >> y2 >> r2;
        dis = distance(x1, y1, x2, y2);

        // 두 터렛이 동일한 위치에 있을 경우
        if(dis == 0){
            if(r1 == r2) cnt = -1;
            else cnt = 0;;
        }
        // 두 터렛이 다른 위치에 있을 경우
        else{
            // 한 점에서 만나는 경우
            if(dis == pow((r1 - r2),2) || dis == pow((r1 + r2), 2)) cnt = 1;
            // 두 점에서 만나는 경우
            else if(dis > pow((r1 - r2),2) && dis < pow((r1 + r2),2)) cnt = 2;

            else cnt = 0;}
        cout << cnt << "\n";

    }
    return 0;
}

사견

한 가지를 간과해서 계속해서 틀린 문제이다.
분명 모든 경우의 수를 고려한 것 같았고 타 블로그 해설을 보아도 나랑 생각이 동일한데 왜 자꾸 틀린걸까 싶었다.

우선, 이 문제에서 생각해야할 경우의 수에 대해 다루어 보자.

두 터렛의 위치가 동일한 경우

    • 반지름의 길이가 같은 경우
    • 두 원이 겹치면서 경우의 수가 무수히 많아진다. (-1)

    • 반지름의 길이가 다른 경우
    • 두 원의 겹치는 부분이 없다. (0)



두 터렛의 위치가 다른 경우

    • 한 점에서 만나는 경우
    • 외접, 내접 이렇게 두가지가 있다.


외접
내접
    • 두 점에서 만나는 경우
    • 만나지 않는 경우

이렇게 5가지이다.

나 같은 경우에는
두 점에서 만나는 경우일때

// 두 점에서 만나는 경우
            else if(dis > pow((r1 - r2),2) && dis < pow((r1 + r2),2)) cnt = 2;

&& 를 사용해 주어야 하는데 ||로 하여 영문모를 오답을 얻었었다.
||을 하게 되면, 두 원이 만나지 않는 경우에도 조건을 충족하게 되어 오답이 된다.

또한,

두 점 사이의 거리를 구할때 제곱 후 sqrt함수, 즉 제곱근을 사용하여 틀린 사람도 있을것이다.
제곱근을 하게 되면 형변환을 하게되면서 값의 손실이 일어나 오답이 생길 수 있으므로
단순히 제곱간의 합을 통해 길이 비교를 하길 바란다.

추가 테스트 케이스

왜 틀리는 지 모르겠다면 이 테스트 케이스를 활용해 보기를 바란다.

입력
7
0 0 1 0 0 1 두 원이 겹치는 경우
0 0 1 0 0 3 중심 좌표는 같지만, 반지름이 다른경우
1 0 1 2 0 2 내접
-1 0 1 2 0 2 외접
1 0 2 3 0 3 두 점에서 만나는 경우
2 0 1 3 0 3 중심좌표가 다르고 만나지 않는다 1 (하나의 원이 다른원 안에 있는경우)
-2 0 1 3 0 3 중심좌표가 다르고 만나지 않는다 2 (하나의 원이 다른원 밖에 있는경우)


출력
-1
0
1
1
2
0
0