번트 문제 질문드립니다.

  • songmw725
    songmw725

    안녕하세요 BUNT문제 질문 드립니다.

    아래원의 면적에서 겹치는 위에 원의 면적을 빼는 형태로 문제를 풀었습니다.

    아래원 면적*1/4 - (원점에서 시작하는 부채꼴+ 3루에서 시작하는 부채꼴 - 원점 3루 교점을 꼭지점으로 하는 삼각형의 넓이)

    이런식으로 풀었구요..

    위의 원의 반지름이 d보다 큰경우 따로 계산해서 불필요하게 뺀 면적을 더해 주었습니다.

    원이 안겹치는 경우는 따로 예외처리해줬습니다.

    아래는 코드 입니다.

    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    const double EPSILON = 1e-9;
    
    struct Vector2 {
      double x, y;
    
      explicit Vector2(double _x =0, double _y =0): x(_x), y(_y) {}
    
      Vector2 operator -(Vector2 r) {
        return Vector2(x-r.x, y-r.y);
      }
    
      double norm() {
        return hypot(x,y);
      }
    
      double dot(Vector2 r) {
        return x*r.x + y*r.y;
      }
      double cross(Vector2 r) {
        return x*r.y-y*r.x;
      }
    
    };
    
    double CircleArea(double r) {
      return r*r*M_PI;
    }
    
    double Theta(double y, double x) {
      return fmod(atan2(y,x)+2*M_PI, 2*M_PI);
    }
    double Theta2(Vector2 a, Vector2 b) {
      return acos(a.dot(b)/(a.norm()*b.norm()));
    }
    
    int main() {
      cout.precision(20);
      ios::sync_with_stdio(false);
      int cases;
      cin >>cases;
      while(cases--) {
        double d, r, v_t, t, v_h;
        cin >> d >> r>> v_t >> t>> v_h;
        double ans =0.0;
        if(fabs(v_h) < EPSILON) {
          // ans = 0;
        } else if(fabs(v_t) < EPSILON) {
          ans = CircleArea(r)/4.0;
        } else {
          double r1 = (d/v_h -t)*v_t;
          if(r+r1 <=d) {
            ans = CircleArea(r)/4.0;
          } else if(r >= d+r1) {
            ans = CircleArea(r)/4.0 - CircleArea(r1)/2.0;
          } else if(r1 >= d+r) {
            //ans = 0.0
          } else {
            double y = (r*r+d*d-r1*r1)/(2*d);
            double x = sqrt(r*r - y*y);
            if(y <=0) {
              //ans = 0.0;
            } else {
              ans = CircleArea(r)/4 - (CircleArea(r)/(2*M_PI)*Theta2(Vector2(x,y), Vector2(0,d)) - d*x/2 + CircleArea(r1)/(2*M_PI)*Theta2(Vector2(0,r1-d), Vector2(x,y-d)));
              if(r1>d) {
                double x2 =sqrt(r1*r1-d*d);
                ans = ans - (CircleArea(r1)/ (2*M_PI)*Theta2(Vector2(0, -d), Vector2(x2 ,-d)) - d*x2/2);
              }
            }
          }
        }
        if(fabs(ans) < EPSILON) cout << "0.0000000000"<<endl;
        else cout << ans << endl;
      }
    }
    

    답변 부탁드립니다
    감사합니다~


    8년 전
1개의 댓글이 있습니다.
  • songmw725
    songmw725

    고려한 케이스는
    위에원 반지름을 r1, 밑에원 반지름을 r이라고 했을 때,
    1) vh가 0인 경우
    2) r+r1<=d인 경우
    3) r>= r1+d인 경우
    3-1) r1> d인 경우
    4) r1>=d+r 인 경우
    5) 두 원의 교점의 y좌표가 <=0인 경우
    6) 예제 같은 경우
    7) 그러면서 r1>d인 경우
    입니다.
    생각못한 케이스가 있을까요 아님 다른 접근방법을 써야할까요??


    8년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.