1. 程式人生 > >LightOJ 1118--Incredible Molecules(兩圓相交)

LightOJ 1118--Incredible Molecules(兩圓相交)

1118 - Incredible Molecules PDF (English) Statistics Forum Time Limit: 0.5 second(s) Memory Limit: 32 MB In the biological lab, you were examining some of the molecules. You got some interesting behavior about some of the molecules. There are some circular molecules, when two of them collide, they overlap with each other, and it’s hard to find that which one is over the other one.

Given two molecules as circles, you have to find the common area of the given molecules that is shaded in the picture.

這裡寫圖片描述

Overlapping Molecules

Input Input starts with an integer T(12)T(12), denoting the number of test cases.

Each case contains six integers x1,y1,r

1x1,y1,r1 and x2,y2,r2x2,y2,r2. Where(x1,y1)(x1,y1)is the center of the first molecule and r1r1is the radius and (x2,y2)(x2,y2)is the center of the second molecule and r2 is the radius. Both the radiuses are positive. No integer will contain more than 3 digits.

Output For each test case, print the case number and the common area of the given molecules. Errors less than 10-6 will be ignored.

Sample Input Output for Sample Input 3

0 0 10 15 0 10

-10 -10 5 0 -10 10

100 100 20 100 110 20

Case 1: 45.3311753978

Case 2: 35.07666099

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
const double PI = acos(-1.0);
typedef struct point {
    double x;
    double y;
    point() {

    }
    point(double a, double b) {
        x = a;
        y = b;
    }
    friend istream& operator >> (istream& in, point&b) {
        in >> b.x >> b.y;
        return in;
    }
    point operator -(const point &b)const {     
        return point(x - b.x, y - b.y);
    }
    point operator +(const point &b)const {     
        return point(x + b.x, y + b.y);
    }
    point operator *(const double &k)const {    
        return point(x * k, y * k);
    }
    point operator /(const double &k)const {    
        return point(x / k, y / k);
    }
    double operator ^(const point &b)const {
        return x*b.y - y*b.x;
    }
    double operator *(const point &b)const {
        return x*b.x + y*b.y;
    }
}point;
typedef struct circle {
    double r;
    point centre;
    friend istream& operator >> (istream &in, circle &b) {
        in >> b.centre >> b.r;
        return in;
    }
    double area() {
        return PI*r*r;
    }
}circle;
double dist(point p1, point p2) {
    return sqrt((p1 - p2)*(p1 - p2));
}
void CircleInterArea(circle a, circle b, double &s1, double &s2) {//相交面積
    double d = dist(a.centre, b.centre);//圓心距
    double t = (d*d + a.r*a.r - b.r*b.r) / (2.0 * d);//
    double h = sqrt((a.r*a.r) - (t*t)) * 2;//h1=h2
    double angle_a = 2 * acos((a.r*a.r + d*d - b.r*b.r) / (2.0 * a.r*d));
    //餘弦公式計算r1對應圓心角,弧度
    double angle_b = 2 * acos((b.r*b.r + d*d - a.r*a.r) / (2.0 * b.r*d));
    //餘弦公式計算r2對應圓心角,弧度
    double la = angle_a*a.r;//r1所對應的相交弧長
    double lb = angle_b*b.r;//r2所對應的相交弧長
    s1 = la*a.r / 2.0 - a.r*a.r*sin(angle_a) / 2.0; //相交部分r1圓的面積
    s2 = lb*b.r / 2.0 - b.r*b.r*sin(angle_b) / 2.0; //相交部分r2圓的面積
                                                    //double rest_s1 = PI*a.r*a.r - s1 - s2;//r1圓剩餘部分面積,不含相交部分面積
                                                    //double rest_s2 = PI*b.r*b.r - s1 - s2;//r1圓剩餘部分面積,不含相交部分面積
}
//兩圓關係
int CircleInterNum(circle a, circle b) {
    double fh = fabs(a.r + b.r), fc = fabs(a.r - b.r), d = dist(a.centre, b.centre);
    if (d>fh)
        return -2;  //外離,沒有交點
    if (d == fh)
        return -1;  //外切,一個交點
    if (d > fc&&d < fh)
        return 0;   //相交,兩個交點
    if (d == fc)
        return 1;   //內切,一個交點
    if (d < fc&&d >= 0)
        return 2;   //內含,沒有交點
}
int main(void) {
    int t;
    cin >> t;
    for (int i = 1; i <= t; i++) {
        circle c1, c2;
        double s1, s2;
        cin >> c1 >> c2;
        int f = CircleInterNum(c1, c2);
        if (f == 0) {
            CircleInterArea(c1, c2, s1, s2);
            printf("Case %d: %.8f\n", i, s1 + s2);
        }
        else if (f == -2 || f == -1) {
            printf("Case %d: 0\n", i);
        }
        else if (f == 1 || f == 2) {
            printf("Case %d: %.8f\n", i,min(c1.area(),c2.area()));
        }
    }
    return 0;
}