题目链接: http://lightoj.com/volume_showproblem.php?problem=1118
http://poj.org/problem?id=2546
题意:给出两圆的圆心和半径,求相交部分面积。
思路:三种情况:外离或外切,内含或内切,相交(这时有两种情况:一圆心在另一圆的内部和外部,效果一样)。
先求出两圆交点 与 连心线与圆的交点 构成的四边形面积,圆心距和两半径用余弦定理解三角形,再用两次余弦定理求出两扇形的圆心角,两扇形面积和减去四边形面积即为答案
自己写的时候讨论的情况相当复杂,代码冗长…………最后参考了 这里 之后大幅优化。
下面给出的代码对应LightOJ,Poj的那道只要改一下输入输出就行了。
代码最后给出了几组LightOJ的测试数据。
今天还发现了一个比较扯的地方,在LightOJ的编译器里没有“abs”函数的定义……“fabs”函数的参数类型可以是int。
在Poj"fabs"函数的参数类型不能是int,int必须用"abs"……
#include <stdio.h>
#include <math.h>
#define PI acos(-1.0)
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
double Deal ()
{
int x1,y1,r1,x2,y2,r2;
scanf("%d%d%d%d%d%d",&x1,&y1,&r1,&x2,&y2,&r2);
double dis=sqrt(1.0*(x1-x2)*(x1-x2)+1.0*(y1-y2)*(y1-y2));
if (dis<=fabs(r1-r2))
return PI*MIN(r1,r2)*MIN(r1,r2);
else if (dis>=r1+r2)
return 0;
else
{
double temp=acos((r1*r1+r2*r2-dis*dis)/(2*r1*r2));
temp=r1*r2*sin(temp);
double temp1=acos((r1*r1+dis*dis-r2*r2)/(2*r1*dis));
temp1=temp1*r1*r1;
double temp2=acos((r2*r2+dis*dis-r1*r1)/(2*r2*dis));
temp2=temp2*r2*r2;
return temp1+temp2-temp;
}
}
int main ()
{
int T;
scanf("%d",&T);
for (int cas=1;cas<=T;cas++)
printf("Case %d: %.8lf\n",cas,Deal());
return 0;
}
/*LightOJ的其他测试数据
Input:
5
0 0 1 10 10 1
0 0 10 0 0 5
-862 823 894 -667 402 663
548 518 145 119 828 620
777 499 712 479 314 967
Output:
Case 1: 0.0
Case 2: 78.5398163397
Case 3: 1139058.0639436883
Case 4: 56622.85922574766
Case 5: 1513681.0685423985
*/