본문 바로가기
프로그래밍/알고리즘

1876 튕기는 볼링공

by 오답노트의 주인 2022. 9. 6.

https://www.acmicpc.net/problem/1876

 

1876번: 튕기는 볼링공

첫째 줄에 테스트 케이스의 개수 N이 주어진다. 다음 N개 줄에는 볼링공과 핀 사이의 거리 T (16.0 ≤ T ≤ 18.0)와 공을 던진 각도 X (중심을 기준으로 계산, 10 ≤ X ≤ 80)가 주어진다. 

www.acmicpc.net


여러 가지 실수를 했기 때문에 조금 아쉬웠다.

문제 자체는 쉬운 편이었으나 삼각함수를 활용하다가 실수를 해서 자꾸 틀렸다. 

접근

볼링공을 굴렸을 때 범퍼에 부딪치면 입사각과 같은 각도로 튕겨진다. 범퍼가 아래에만 있는게 아니라 위에도 있으므로 양 옆 범퍼를 모두 부딪치면서 전진하게 된다.

 

문제를 푸는 방법은 볼링공을 움직이면서 볼링공과 핀의 거리를 구했을 때 둘의 반지름을 합한 값보다 작은 상황이 있는지 검사하면 된다. 

 

그런데 양 범퍼를 부딪치며 전진하는 볼링공과 핀의 거리를 구하기 매우 어려우므로 단순하게 볼링공이 레인의 중앙에 있을 때만 확인하기로 했다.

 

볼링공이 이동할 때 핀과 접하게 된다면 볼링공이 레인의 중앙에 있을 때 볼링공과 핀의 거리는 //[a+b]//이다.

만약 볼링공이 이동할 때 핀과 부딪친다면 볼링공과 핀의 거리는 //[a+b]//보다 더 짧을 것이다. 그렇지 않다면 부딪치지 않을 것이다.

입사각이 주어졌고, 볼링공과 핀의 반지름도 주어졌으므로

$$ a+b = {6\over{cos{({\pi\over 2}-\theta)}}} + {10\over{cos{({\pi\over 2}-\theta)}}} = {6\over{sin\theta}} + {10\over{sin\theta}} \\ = {16\over{sin\theta}}$$

 

사진에서 알 수 있듯이 볼링공이 접하는 경우는 두 가지가 있으므로 볼링공이 //[ (T-a-b, T+a+b) ]//범위 내에 있다면 충돌임을 알 수 있다.

 

이제 볼링공을 움직여 보면서 거리가 가까운 상황이 있는지 검사하자.

 

볼링공이 범퍼와 부딪치고 다시 레인의 중앙으로 왔을 때 얼마나 이동했는지 알기 위해 다음 사진을 참고하자.

레인의 절반은 //[105/2=52.5]//다. 볼링공이 범퍼를 쳤을 때 볼링공의 반지름을 고려해야 하므로 세로는 //[52.5-10 = 42.5]//다. 

 

따라서 //[x = {42.5\over{tan\theta}}]//인데, 부딪친 후 다시 중앙으로 향하므로 2를 곱해야한다. 

 

한 번 부딪쳤을 때 이동거리 //[ = 2x = {85\over{tan\theta}} ]//

 

따라서 0부터 //[T * 100]//까지 이동거리를 누적시키면서 충돌 범위 내에 있었는지 검사하면 된다.

미흡했던 점

문제 분석은 30분만에 끝냈지만 코드를 짜는 과정에서 라디안과 각의 관계, 삼각함수 사용법 등 실수를 했다.

 

//[180\degree = \pi, 1rad = {\pi\over{180\degree}}]//이다. cmath의 삼각함수들은 전부 radian으로 값을 입력받아야 하는데 이걸 모르고 degree를 그대로 입력했다. 이런 관계는 암기가 되어 있어야 한다. 


#include <cmath>
#include <iostream>
#define PI 3.14159265
int main() {
  int N;
  scanf("%d", &N);
  for (int i = 0; i < N; i++) {
    double T, dist = 0;
    int X;
    scanf("%lf %d", &T, &X);
    double left = T * 100 - (16.0 / sin(PI * X / 180.0)),
           right = T * 100 + (16.0 / sin(PI * X / 180.0)),
           step = 85.0 / tan(PI * X / 180.0);
    while (dist < right) {
      if (left < dist && dist < right) {
        printf("yes\n");
        break;
      }
      dist += step;
    }
    if (dist >= right) {
      printf("no\n");
    }
  }
}

 

'프로그래밍 > 알고리즘' 카테고리의 다른 글

9465 스티커  (0) 2022.09.10
2502 떡 먹는 호랑이  (0) 2022.09.07
4105 유클리드  (0) 2022.09.05
2527 직사각형  (0) 2022.09.03
18187 평면 분할  (0) 2022.09.03

댓글