LightOJ 1118--Incredible Molecules(两圆相交)

1118 - Incredible Molecules
 
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), denoting the number of test cases.

Each case contains six integers x1, y1, r1 and x2, y2, r2. Where (x1, y1) is the center of the first molecule and r1 is the radius and (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

Case 3: 860.84369

首先,判断两圆关系,如果相交(两个交点),则求出相交的面积,外离和外切相交面积为0.

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<cstdio>
  5 using namespace std;
  6 const double PI = acos(-1.0);
  7 typedef struct point {
  8     double x;
  9     double y;
 10     point() {
 11 
 12     }
 13     point(double a, double b) {
 14         x = a;
 15         y = b;
 16     }
 17     friend istream& operator >> (istream& in, point&b) {
 18         in >> b.x >> b.y;
 19         return in;
 20     }
 21     point operator -(const point &b)const {        
 22         return point(x - b.x, y - b.y);
 23     }
 24     point operator +(const point &b)const {        
 25         return point(x + b.x, y + b.y);
 26     }
 27     point operator *(const double &k)const {    
 28         return point(x * k, y * k);
 29     }
 30     point operator /(const double &k)const {    
 31         return point(x / k, y / k);
 32     }
 33     double operator ^(const point &b)const {
 34         return x*b.y - y*b.x;
 35     }
 36     double operator *(const point &b)const {
 37         return x*b.x + y*b.y;
 38     }
 39 }point;
 40 typedef struct circle {
 41     double r;
 42     point centre;
 43     friend istream& operator >> (istream &in, circle &b) {
 44         in >> b.centre >> b.r;
 45         return in;
 46     }
 47     double area() {
 48         return PI*r*r;
 49     }
 50 }circle;
 51 double dist(point p1, point p2) {
 52     return sqrt((p1 - p2)*(p1 - p2));
 53 }
 54 void CircleInterArea(circle a, circle b, double &s1, double &s2) {//相交面积
 55     double d = dist(a.centre, b.centre);//圆心距
 56     double t = (d*d + a.r*a.r - b.r*b.r) / (2.0 * d);//
 57     double h = sqrt((a.r*a.r) - (t*t)) * 2;//h1=h2
 58     double angle_a = 2 * acos((a.r*a.r + d*d - b.r*b.r) / (2.0 * a.r*d));
 59     //余弦公式计算r1对应圆心角,弧度
 60     double angle_b = 2 * acos((b.r*b.r + d*d - a.r*a.r) / (2.0 * b.r*d));
 61     //余弦公式计算r2对应圆心角,弧度
 62     double la = angle_a*a.r;//r1所对应的相交弧长
 63     double lb = angle_b*b.r;//r2所对应的相交弧长
 64     s1 = la*a.r / 2.0 - a.r*a.r*sin(angle_a) / 2.0;    //相交部分r1圆的面积
 65     s2 = lb*b.r / 2.0 - b.r*b.r*sin(angle_b) / 2.0;    //相交部分r2圆的面积
 66                                                     //double rest_s1 = PI*a.r*a.r - s1 - s2;//r1圆剩余部分面积,不含相交部分面积
 67                                                     //double rest_s2 = PI*b.r*b.r - s1 - s2;//r1圆剩余部分面积,不含相交部分面积
 68 }
 69 //两圆关系
 70 int CircleInterNum(circle a, circle b) {
 71     double fh = fabs(a.r + b.r), fc = fabs(a.r - b.r), d = dist(a.centre, b.centre);
 72     if (d>fh)
 73         return -2;    //外离,没有交点
 74     if (d == fh)
 75         return -1;    //外切,一个交点
 76     if (d > fc&&d < fh)
 77         return 0;    //相交,两个交点
 78     if (d == fc)
 79         return 1;    //内切,一个交点
 80     if (d < fc&&d >= 0)
 81         return 2;    //内含,没有交点
 82 }
 83 int main(void) {
 84     int t;
 85     cin >> t;
 86     for (int i = 1; i <= t; i++) {
 87         circle c1, c2;
 88         double s1, s2;
 89         cin >> c1 >> c2;
 90         int f = CircleInterNum(c1, c2);
 91         if (f == 0) {
 92             CircleInterArea(c1, c2, s1, s2);
 93             printf("Case %d: %.8f
", i, s1 + s2);
 94         }
 95         else if (f == -2 || f == -1) {
 96             printf("Case %d: 0
", i);
 97         }
 98         else if (f == 1 || f == 2) {
 99             printf("Case %d: %.8f
", i,min(c1.area(),c2.area()));
100         }
101     }
102     return 0;
103 }
View Code
原文地址:https://www.cnblogs.com/FlyerBird/p/9630320.html