1. 程式人生 > >HDU 5120 Intersection (計算幾何)2014ICPC 北京站現場賽

HDU 5120 Intersection (計算幾何)2014ICPC 北京站現場賽

Intersection

Time Limit: 4000/4000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 1253    Accepted Submission(s): 487


Problem Description Matt is a big fan of logo design. Recently he falls in love with logo made up by rings. The following figures are some famous examples you may know.


A ring is a 2-D figure bounded by two circles sharing the common center. The radius for these circles are denoted by r and R (r < R). For more details, refer to the gray part in the illustration below.


Matt just designed a new logo consisting of two rings with the same size in the 2-D plane. For his interests, Matt would like to know the area of the intersection of these two rings.
Input The first line contains only one integer T (T ≤ 105
), which indicates the number of test cases. For each test case, the first line contains two integers r, R (0 ≤ r < R ≤ 10).

Each of the following two lines contains two integers xi, yi (0 ≤ xi, yi ≤ 20) indicating the coordinates of the center of each ring.
Output For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y is the area of intersection rounded to 6 decimal places.

Sample Input 2 2 3 0 0 0 0 2 3 0 0 5 0
Sample Output Case #1: 15.707963 Case #2: 2.250778

題意:給出兩個圓環的半徑和圓心,求他們重合部分的面積,聽說是模板題,隊友做的。

分析:計算幾何。

#include <cstdio>
#include <cmath>
using namespace std;

#define PI acos(-1.0) //定義PI

struct Circle { // 定義圓
    double x, y;
    double r;
};

struct Ring { // 定義圓環
    double x, y;
    double R, r;
};

struct Get_Intersection_RingAndRing {

    //求圓心距,即兩個圓心之間的距離
    double get_dis(double x1, double y1, double x2, double y2) {
        return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    // 求兩圓的相交面積
    double get_CircleIntersectionArea(Circle c1, Circle c2) {
        double dis = get_dis(c1.x, c1.y, c2.x, c2.y);

        // 圓心距大於半徑和,兩圓相交面積為0
        if(dis >= c1.r + c2.r) return 0;

        double min_r = c1.r < c2.r ? c1.r : c2.r;
        double max_r = c1.r > c2.r ? c1.r : c2.r;
        if(min_r + dis <= max_r)  //圓心距小於半徑之差,兩圓包含關係
            return PI * min_r * min_r;

        double a = acos((c1.r * c1.r + dis * dis - c2.r * c2.r) / 2 / c1.r / dis);
        double b = acos((c2.r * c2.r + dis * dis - c1.r * c1.r) / 2 / c2.r / dis);
        double area1 = a * c1.r * c1.r; //第一個圓中扇形的面積, 弧長L=a*c1.r,面積等於0.5*L*c1.r
        double area2 = b * c2.r * c2.r; //第二個圓中扇形的面積
        double ans = area1 + area2; //兩個扇形的面積和等於四邊形的面積加上兩圓相交的面積
        double area_qua = sin(a) * c1.r * dis; //四邊形的面積
        ans -= area_qua;
        return ans;
    }

    //求圓環和圓環的相交面積
    double Get_IntersectionArea(Ring r1, Ring r2) {
        Circle a1, a2, b1, b2;
        a1.x = r1.x, a1.y = r1.y, a1.r = r1.r;
        a2.x = r1.x, a2.y = r1.y, a2.r = r1.R;
        b1.x = r2.x, b1.y = r2.y, b1.r = r2.r;
        b2.x = r2.x, b2.y = r2.y, b2.r = r2.R;
        return get_CircleIntersectionArea(a2, b2) - get_CircleIntersectionArea(a1, b2) - get_CircleIntersectionArea(a2, b1) + get_CircleIntersectionArea(a1, b1);
    }
};

int main()
{
    int t;
    Ring r1, r2;
    Get_Intersection_RingAndRing x;
    scanf("%d",&t);
    int cas=1;
    while(t--)
   {
        scanf("%lf%lf",&r1.r, &r1.R);
        r2.r = r1.r, r2.R = r1.R;
        scanf("%lf%lf",&r1.x, &r1.y);
        scanf("%lf%lf", &r2.x, &r2.y);

        printf("Case #%d: %.6lf\n", cas++, x.Get_IntersectionArea(r1, r2));
    }
    return 0;
}

題目連結:點選開啟連結