题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5120
题意: 给定相同的两个圆环的位置,求圆环的相交面积。
思路:分解成圆的相交问题即可。设S(r1, r2)表示圆r1和r2的相交面积。第一个圆环的大小半径分别为R1,r1,第二个为R2,r2;
若两圆环无相交部分,则输出0;
若两圆环相交,分三种情况:
1. 仅仅只有外部的圆,即只有R1和R2相交
则直接用圆的相交计算。 S = S(R1,R2);
2. r1和r2不相交,但是R1和r2相交,R2和r1相交
则 S = S(R1, R2) - 2*S(R1, r2);
3.r1和r2相交
则 S = S(R1, R2)- 2*S(R1, r2)+ S(r1, r2)。
综上所述:得到所有情况的圆环相交公式:
S = S(R1, R2)- 2*S(R1, r2)+ S(r1, r2);
可能需要注意的几点:
1. π 用 arcsin( -1.0 ) 精度会更高
2. 注意求圆交面积的计算方法导致的精度误差
代码如下:
#include <cstdio> #include <algorithm> #include <cmath> #define PI acos(-1.0) using namespace std; struct Point { int x, y; }a, b; int r, R; double getS(int r1, int r2){ int d = (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); if(d >= (r1+r2)*(r1+r2)) return 0.0; if(d <= (r1-r2)*(r1-r2)) return (double)PI*r2*r2; double d2 = (r2*r2 - r1*r1 + d*1.0)/(2.0*sqrt(d)); double d1 = sqrt(d) - d2; double ang1 = acos((double)d1/r1), ang2 = acos((double)d2/r2); return ang1*r1*r1 + ang2*r2*r2 - sqrt(d)*r1*sin(ang1); } int main(){ int t, tc = 0; // freopen("in.txt", "r", stdin); scanf("%d", &t); while(t--){ int n; scanf("%d%d", &r, &R); scanf("%d%d%d%d", &a.x, &a.y, &b.x, &b.y); printf("Case #%d: %.6f\n", ++tc, getS(R, R) - 2*getS(R, r) + getS(r, r)); } return 0; }