题目大意
求矩形和圆的交
简要题解
嚯嚯嚯,我会暴力积分!
调了一整天参数,Wrong Answer on Test 2.
爆粗口了,真是没办法,谁叫我弱呢。。
老老实实写精确做法吧。
其实要求的就是三角形和圆的交嘛,9种情况全部讨论一下就好~
啊摔!去你大爷的,你知道这有多难写吗??
有向面积大法好~
来看三张图就明白了~
然后就愉快地写呗~
好久没写计算几何了,不过好像我都会实现欸。
然后写完了,好开心~
然后对拍,拍一次错一次,爆粗口×2
要知道我为这道傻缺题已经花了两天了。
血的教训:计算几何千万不要觉得是对的就写,细节会让你明白,你写的全是错的。
所以,有板子就上板子,现推什么的出错的概率太高了。
写完后我发现,这道题我写的调试代码长度是源代码长度的两倍。。爆粗口×3
最坑的地方就是有相交时的处理,GeoGebra是个好软件,可也架不住我个智障选手啊。。
拍了n次,画了n张图,然后发现愚蠢的错误爆n次粗口,然后在图书馆众目睽睽之下抽自己n次耳光。
终于Accept了~
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace my_header { 4 #define pb push_back 5 #define mp make_pair 6 #define pir pair<int, int> 7 #define vec vector<int> 8 #define pc putchar 9 #define clr(t) memset(t, 0, sizeof t) 10 #define pse(t, v) memset(t, v, sizeof t) 11 #define bl puts("") 12 #define wn(x) wr(x), bl 13 #define ws(x) wr(x), pc(' ') 14 const int INF = 0x3f3f3f3f; 15 typedef long long LL; 16 typedef double DB; 17 inline char gchar() { 18 char ret = getchar(); 19 for(; (ret == ' ' || ret == ' ' || ret == ' ') && ret != EOF; ret = getchar()); 20 return ret; } 21 template<class T> inline void fr(T &ret, char c = ' ', int flg = 1) { 22 for(c = getchar(); (c < '0' || '9' < c) && c != '-'; c = getchar()); 23 if (c == '-') { flg = -1; c = getchar(); } 24 for(ret = 0; '0' <= c && c <= '9'; c = getchar()) 25 ret = ret * 10 + c - '0'; 26 ret = ret * flg; } 27 inline int fr() { int t; fr(t); return t; } 28 template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); } 29 template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); } 30 template<class T> inline char wr(T a, int b = 10, bool p = 1) { 31 return a < 0 ? pc('-'), wr(-a, b, 0) : (a == 0 ? (p ? pc('0') : p) : 32 (wr(a/b, b, 0), pc('0' + a % b))); 33 } 34 template<class T> inline void wt(T a) { wn(a); } 35 template<class T> inline void wt(T a, T b) { ws(a), wn(b); } 36 template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); } 37 template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); } 38 template<class T> inline T gcd(T a, T b) { 39 return b == 0 ? a : gcd(b, a % b); } 40 template<class T> inline T fpw(T b, T i, T _m, T r = 1) { 41 for(; i; i >>= 1, b = b * b % _m) 42 if(i & 1) r = r * b % _m; 43 return r; } 44 }; 45 using namespace my_header; 46 47 48 const DB PI = 3.1415926535897932384626; 49 const DB EPS = 1e-6; 50 int sgn(DB x) { 51 return x < -EPS ? -1 : EPS < x; 52 } 53 54 #define Vector Point 55 struct Point { 56 DB x, y; 57 Point() {} 58 Point(DB x, DB y):x(x), y(y) {} 59 Vector operator + (Vector); 60 Vector operator - (Vector); 61 Vector operator * (DB); 62 Vector operator / (DB); 63 DB getCross(Vector); 64 DB getDot(Vector); 65 DB getLength(); 66 DB getAngle(Vector); 67 Vector getNorm(); 68 Vector Rotate(DB); 69 }; 70 71 72 struct Circle { 73 Point o; 74 DB r; 75 DB getSectorArea(DB); 76 vector<Point> getSegmentIntersection(Point, Point); 77 }; 78 79 DB getSegmentCirlcleProjectionArea(Circle, Point, Point); 80 DB getTriangleCircleIntersectionArea(Circle, Point, Point, Point); 81 bool onSegment(Point, Point, Point); 82 83 int main() { 84 #ifdef lol 85 freopen("F.in", "r", stdin); 86 freopen("F.out", "w", stdout); 87 #else 88 freopen("mammoth.in", "r", stdin); 89 freopen("mammoth.out", "w", stdout); 90 #endif 91 92 Circle c; 93 Point a, b; 94 cin >> c.o.x >> c.o.y >> c.r; 95 cin >> a.x >> a.y; 96 cin >> b.x >> b.y; 97 if (b.x < a.x) swap(a.x, b.x); 98 if (b.y < a.y) swap(a.y, b.y); 99 100 DB ans = 0; 101 ans += getTriangleCircleIntersectionArea(c, a, Point(a.x, b.y), b); 102 ans += getTriangleCircleIntersectionArea(c, a, Point(b.x, a.y), b); 103 printf("%.8lf ", ans); 104 return 0; 105 } 106 107 DB getSegmentCirlcleProjectionArea(Circle C, Point a, Point b) { 108 vector<Point> t = C.getSegmentIntersection(a, b); 109 if (t.size() == 0) { 110 if ((a - C.o).getLength() < C.r + EPS && (b - C.o).getLength() < C.r + EPS) 111 return (a - C.o).getCross(b - C.o) / 2; 112 return C.getSectorArea((a - C.o).getAngle(b - C.o)); 113 } 114 if (t.size() == 1) { 115 Point c = t.at(0); 116 if ((a - C.o).getLength() <= C.r) { 117 return C.getSectorArea((c - C.o).getAngle(b - C.o)) + (a - C.o).getCross(c - C.o) / 2; 118 } 119 else { 120 return C.getSectorArea((a - C.o).getAngle(c - C.o)) + (c - C.o).getCross(b - C.o) / 2; 121 } 122 } 123 return C.getSectorArea((a - C.o).getAngle(t[0] - C.o)) + (t[0] - C.o).getCross(t[1] - C.o) / 2 + C.getSectorArea((t[1] - C.o).getAngle(b - C.o)); 124 } 125 126 DB getTriangleCircleIntersectionArea(Circle C, Point a, Point b, Point c) { 127 DB res = 0; 128 res += getSegmentCirlcleProjectionArea(C, a, b); 129 res += getSegmentCirlcleProjectionArea(C, b, c); 130 res += getSegmentCirlcleProjectionArea(C, c, a); 131 return fabs(res); 132 } 133 134 Vector Vector::operator + (Vector b) { 135 return Vector(x + b.x, y + b.y); 136 } 137 Vector Vector::operator - (Vector b) { 138 return Vector(x - b.x, y - b.y); 139 } 140 Vector Vector::operator * (DB b) { 141 return Vector(x * b, y * b); 142 } 143 Vector Vector::operator / (DB b) { 144 return Vector(x / b, y / b); 145 } 146 DB Vector::getCross(Vector b) { 147 return x * b.y - y * b.x; 148 } 149 DB Vector::getDot(Vector b) { 150 return x * b.x + y * b.y; 151 } 152 DB Vector::getLength() { 153 return sqrt(this->getDot(*this)); 154 } 155 Vector Vector::Rotate(DB ang) { 156 DB c = cos(ang), s = sin(ang); 157 return Vector(c * x - s * y, s * x + c * y); 158 } 159 Vector Vector::getNorm() { 160 DB l = this->getLength(); 161 return Vector(x / l, y / l); 162 } 163 DB Vector::getAngle(Vector b) { 164 DB t = atan2(b.y, b.x) - atan2(y, x); 165 while (t > PI) 166 t -= 2 * PI; 167 while (t < -PI) 168 t += 2 * PI; 169 return t; 170 } 171 172 bool onSegment(Point a, Point b, Point c) { 173 return sgn((c - a).getDot(b - a)) > 0 && sgn((c - b).getDot(a - b)) > 0; 174 } 175 176 DB Circle::getSectorArea(DB ang) { 177 return ang * r * r / 2; 178 } 179 vector<Point> Circle::getSegmentIntersection(Point a, Point b) { 180 vector<Point> res; 181 Point p = a + (b - a).getNorm() * (b - a).getDot(o - a) / (b - a).getLength(); 182 if ((p - o).getLength() >= r) 183 return res; 184 DB d = sqrt(r * r - (p - o).getDot(p - o)); 185 Vector tmp = (b - a).getNorm() * d; 186 if (onSegment(a, b, p - tmp)) 187 res.push_back(p - tmp); 188 if (onSegment(a, b, p + tmp)) 189 res.push_back(p + tmp); 190 return res; 191 }