Intersection
Time Limit: 4000/4000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 4238 Accepted Submission(s): 1623
Problem Description
Matt is a big fan of logo design. Recently he falls in love with logo made up by rings. The following figures are some famous examples you may know.
A ring is a 2-D figure bounded by two circles sharing the common center. The radius for these circles are denoted by r and R (r < R). For more details, refer to the gray part in the illustration below.
Matt just designed a new logo consisting of two rings with the same size in the 2-D plane. For his interests, Matt would like to know the area of the intersection of these two rings.
A ring is a 2-D figure bounded by two circles sharing the common center. The radius for these circles are denoted by r and R (r < R). For more details, refer to the gray part in the illustration below.
Matt just designed a new logo consisting of two rings with the same size in the 2-D plane. For his interests, Matt would like to know the area of the intersection of these two rings.
Input
The first line contains only one integer T (T ≤ 105), which indicates the number of test cases. For each test case, the first line contains two integers r, R (0 ≤ r < R ≤ 10).
Each of the following two lines contains two integers xi, yi (0 ≤ xi, yi ≤ 20) indicating the coordinates of the center of each ring.
Each of the following two lines contains two integers xi, yi (0 ≤ xi, yi ≤ 20) indicating the coordinates of the center of each ring.
Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y is the area of intersection rounded to 6 decimal places.
Sample Input
2
2 3
0 0
0 0
2 3
0 0
5 0
Sample Output
Case #1: 15.707963
Case #2: 2.250778
Source
Recommend
liuyiding
参考代码:
1 #include <bits/stdc++.h> 2 #define INF 0x3f3f3f3f 3 #define rep(i,a,n) for(int i=a;i<n;++i) 4 #define per(i,a,n) for(int i=n-1;i>=a;--i) 5 using namespace std; 6 typedef long long ll; 7 const double eps = 1e-10; 8 const double PI = acos(-1.0); 9 const int maxn = 2500; //注意修改 10 int n; 11 //有的命名为sgn函数,高精度符号判断 12 int dcmp(double x) 13 { 14 //相等函数判断,减少精度问题 15 if(fabs(x) < eps) return 0; 16 else return x < 0 ? -1 : 1; 17 } 18 //点的定义 19 class Point 20 { 21 public: 22 double x, y; 23 Point(double x = 0, double y = 0): x(x), y(y) {} //构造函数,方便代码的编写 24 } point[maxn], pafter[maxn]; 25 26 typedef Point Vector;// 从程序实现上,Vector只是Point的别名 27 28 //运算符重载 29 Vector operator + (const Vector &A, const Vector &B) 30 { 31 return Vector(A.x + B.x, A.y + B.y); //向量+向量=向量,点+向量=点 32 } 33 Vector operator - (const Vector &A, const Vector &B) 34 { 35 return Vector(A.x - B.x, A.y - B.y); //向量-向量=向量,点-向量-点 36 } 37 Vector operator * (const Vector &A, double p) 38 { 39 return Vector(A.x * p, A.y * p); //向量*数=向量 (数乘) 40 } 41 Vector operator / (const Vector &A, double p) 42 { 43 return Vector(A.x / p, A.y / p); //向量/数=向量 (数除) 44 } 45 double operator * (const Vector &A, const Vector &B) 46 { 47 return A.x * B.x + A.y * B.y; //向量(点乘)向量=数 (点乘) 48 } 49 bool operator < (const Point &A, const Point &B) 50 { 51 return A.x == B.x ? A.y < B.y : A.x < B.x; //按x值递增排序 52 } 53 bool operator == (const Point &A, const Point &B) 54 { 55 return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; //判定两个点是否相同,用到dcmp精度判定 56 } 57 58 //点乘叉乘 59 double dot(const Vector &A, const Vector &B) 60 { 61 return A.x * B.x + A.y * B.y; //向量(叉乘)向量=向量 (叉乘) 62 } 63 double operator ^ (const Vector &A, const Vector &B) 64 { 65 return A.x * B.y - A.y * B.x; 66 } 67 double cross(const Vector &A, const Vector &B) 68 { 69 return A.x * B.y - A.y * B.x; 70 } 71 72 //模长面积 73 double abs(const Vector &A) 74 { 75 return sqrt(dot(A, A)); //计算向量模长 76 } 77 double area2(const Point &A, const Point &B, const Point &C) 78 { 79 return cross(B - A, C - A) ; //计算平行四边形方向面积 80 } 81 double PolygonArea(Point *p, int n) 82 { 83 double area = 0; //计算多边形的有向面积 84 rep(i, 1, n - 1) 85 { 86 area += cross(p[i] - p[0], p[i + 1] - p[0]); 87 } 88 return area / 2.0; 89 } 90 91 //旋转 92 Vector rotate(Vector A, double rad) 93 { 94 return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad)); //旋转rad弧度 95 } 96 Vector normal(Vector A) 97 { 98 double l = abs(A); //计算单位法线,左转90 99 return Vector(-A.y / l, A.x / l); 100 } 101 double torad(double deg) 102 { 103 return deg / 180 * acos(-1); //角度转弧度 104 } 105 106 //线段定义 107 class Line 108 { 109 public: 110 Point s, e; 111 Line() {} 112 Line(Point _s, Point _e) 113 { 114 s = _s; 115 e = _e; 116 } 117 118 } line[maxn]; 119 bool inter(Line l1, Line l2) 120 { 121 return ( 122 max(l1.s.x, l1.e.x) >= min(l2.s.x, l2.e.x) && 123 max(l2.s.x, l2.e.x) >= min(l1.s.x, l1.e.x) && 124 max(l1.s.y, l1.e.y) >= min(l2.s.y, l2.e.y) && 125 max(l2.s.y, l2.e.y) >= min(l1.s.y, l1.e.y) && 126 dcmp((l2.s - l1.s) ^ (l1.s - l1.e)) * dcmp((l2.e-l1.s) ^ (l1.s - l1.e)) < 0 && 127 dcmp((l1.s - l2.s) ^ (l2.s - l2.e)) * dcmp((l1.e-l2.s) ^ (l2.s - l2.e)) < 0 128 ) ; 129 } 130 131 bool inter(Point a1, Point a2, Point b1, Point b2) 132 { 133 Line l1(a1, a2), l2(b1, b2); 134 return inter(l1, l2); 135 } 136 137 bool cmp(Point a, Point b) 138 { 139 if(a.x == b.x) return a.y < b.y; 140 else return a.x < b.x; 141 } 142 143 double dist(Point a, Point b) 144 { 145 return sqrt((a - b) * (a - b)); 146 } 147 148 //求两直线交点 149 Point getinter(Line l1, Line l2) 150 { 151 Vector v = l1.s - l1.e; 152 Vector w = l2.s - l2.e; 153 Vector u = l1.e-l2.e; 154 double t = cross(w, u) / cross(v, w); 155 return l1.e+v * t; 156 } 157 Point getinter(Point a1, Point a2, Point b1, Point b2) 158 { 159 Line l1(a1, a2); 160 Line l2(b1, b2); 161 return getinter(l1, l2); 162 } 163 //判定点和线段的关系, 164 //0:不在线段所在直线上 165 //1:在线段内(不含端点) 166 //2:在线段端点 167 //3:在线段两侧的射线上 168 int online(Point a, Line l) 169 { 170 if(dcmp(cross(l.s - a, l.e-a)) != 0) return 0; 171 double pans = dcmp(dot(l.s - a, l.e-a)); 172 if(pans < 0) return 1; 173 else if(pans == 0) return 2; 174 else if(pans > 0) return 3; 175 } 176 177 int online(Point a, Point b1, Point b2) 178 { 179 Line l(b1, b2); 180 return online(a, l); 181 } 182 183 int sgn(double x) 184 { 185 if(fabs(x) < eps) return 0; 186 if(x < 0) return -1; 187 else return 1; 188 } 189 190 double Area_of_overlap(Point c1, double r1, Point c2, double r2) 191 { 192 double d = dist(c1, c2); 193 if(r1 + r2 < d + eps) return 0; 194 if(d < fabs(r1 - r2) + eps) 195 { 196 double r = min(r1, r2); 197 return PI * r * r; 198 } 199 double x = (d * d + r1 * r1 - r2 * r2) / (2 * d); 200 double t1 = acos(x / r1); 201 double t2 = acos((d - x) / r2); 202 return r1 * r1 * t1 + r2 * r2 * t2 - d * r1 * sin(t1); 203 } 204 205 int t; 206 double RR, rr; 207 double xx1, yy1, xx2, yy2; 208 int main() 209 { 210 ios::sync_with_stdio(false); 211 cin >> t; 212 rep(tt, 1, t + 1) 213 { 214 cin >> rr >> RR >> xx1 >> yy1 >> xx2 >> yy2; 215 double ans1, ans2, ans3, ans4; 216 ans1 = Area_of_overlap(Point(xx1, yy1), RR, Point(xx2, yy2), RR); 217 ans2 = Area_of_overlap(Point(xx1, yy1), RR, Point(xx2, yy2), rr); 218 ans3 = Area_of_overlap(Point(xx1, yy1), rr, Point(xx2, yy2), RR); 219 ans4 = Area_of_overlap(Point(xx1, yy1), rr, Point(xx2, yy2), rr); 220 cout << "Case #" << tt << ": "; 221 cout << fixed << setprecision(6) << ans1 - ans2 - ans3 + ans4 << endl; 222 } 223 return 0; 224 }