题目链接:http://acm.tju.edu.cn/toj/showp1754.html
Time Limit: 1.0 Seconds Memory Limit: 65536K
Total Runs: 881 Accepted Runs: 313 Multiple test files
Your task is to write a program, which, given two circles, calculates the area of their intersection with the accuracy of three digits after decimal point.
InputIn the single line of input file there are space-separated real numbers x1 y1 r1 x2 y2 r2. They represent center coordinates and radii of two circles.
OutputThe output file must contain single real number - the area rounded to three decimal places.
Sample Input
20.0 30.0 15.0 40.0 30.0 30.0Sample Output
608.366
Source: Northeastern Europe 2000 Far-Eastern Subregion
圆的位置关系,按照两个圆的圆心间距 d 由远到近的顺序,可分为:
(两圆半径,R >= r)
相离,d > R+r;
相外切,d = R+r;
相交,R-r < d < R+r;
相内切,d = R-r;
内含:d < R-r。
本题要求输出两个圆相交的面积,所以需要先判断两个圆的位置关系,然后根据情况计算就可以了。注意相交有两种情况,故需要使
ra*ra*angle1+rb*rb*angle2-ra*l*sin(angle1)
中的ra为大圆半径。
#include <stdio.h>
#include <cmath>
#define PI acos(-1.0)
#define swap(a,b) {a=a+b;b=a-b;a=a-b;}
using namespace std;
struct point{
double x,y;
};
double distance(point a,point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double Circular(point a,double ra,point b,double rb){
double l=distance(a,b);
if(ra<rb) //注意这里必须要找出最大值,因为下面减去ra*l*sin(angle1)时必须确保ra是大圆
swap(ra,rb);
if(l>=(ra+rb))
return 0;
if(l<=(ra-rb))
return rb*rb*PI;
double angle1=acos((l*l+ra*ra-rb*rb)/(2*l*ra));
double angle2=acos((l*l+rb*rb-ra*ra)/(2*l*rb));
return ra*ra*angle1+rb*rb*angle2-ra*l*sin(angle1);
}
int main(){
point a,b;
double ra,rb;
while(~scanf("%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&ra,&b.x,&b.y,&rb))
printf("%.3lf\n",Circular(a,ra,b,rb));
}