题意:

给出一个\(n\)个点的简单多边形,和两个点\(A, B\)还有一个常数\(k(0.2 \leq k < 0.8)\)。

点\(P\)满足\(\left | PB \right | \leq k \left | PA \right |\),求点\(P\)构成的图形与多边形相交的面积。

分析:

推导圆的公式:

高中应该做过这样的题目,我们很容易知道这是一个圆。

下面推导一下圆的方程:

设\(A(x_1, y_1),B(x_2,y_2),P(x,y)\),根据条件列出等式:

\(\sqrt{(x-x_2)^2+(y-y_2)^2}=k\sqrt{(x-x_1)^2+(y-y_1)^2}\)

\(\Rightarrow (x-x_2)^2+(y-y_2)^2=k^2 \left [ (x-x_1)^2+(y-y_1)^2 \right ]\)

展开整理得:

\((1-k^2)x^2-2(x_2-k^2x_1)x+(x_2^2-k^2x_1^2)+(1-k^2)y^2-2(y_2-k^2y_1)y+(y_2^2-k^2y_1^2)=0\)

\(\Rightarrow x^2+y^2-2\frac{x_2-k^2x_1}{1-k^2}x-2\frac{y_2-k^2y_1}{1-k^2}y+\frac{x_2^2+y_2^2-k^2(x_1^2+y_1^2)}{1-k^2}=0\)

对于圆的一般式\(x^2+y^2+Dx+Ey+F=0\),可以用配方法知道圆心为\((-\frac{D}{2},-\frac{E}{2})\),半径为\(\frac{\sqrt{D^2+E^2-4F}}{2}\)

计算多边形与圆的面积交

根据以往的经验,多边形的问题都是要分解成若干三角形的。

对于多边形的每条边,我们可以先求该线段与圆心构成三角形的面积交。

会有下面几种情况:

  1. 两个点都在圆的内部,此时相交的面积为三角形的面积

  2. 一个点在圆内,一个点在圆外,相交的面积可以分解为一个扇形一个三角形的面积

  3. 两个点都在圆外,而且线段和圆没有交点或者相切,相交的面积为一个扇形

  4. 两个点都在圆外,而且线段和圆有两个交点,相交的面积可以分解为两个扇形一个三角形

我们求出每个三角形与圆的面积交以后,根据叉积的正负来计算面积的面积的正负,最后再取个绝对值就是整个多边形与圆的面积交。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <map>
  6. #include <cmath>
  7. //#define DEBUG
  8. using namespace std;
  9. const double eps = 1e-10;
  10. const double PI = acos(-1.0);
  11. const double TOW_PI = PI * 2.0;
  12. int dcmp(double x) {
  13. if(fabs(x) < eps) return 0;
  14. return x < 0 ? -1 : 1;
  15. }
  16. struct Point
  17. {
  18. double x, y;
  19. void read() { scanf("%lf%lf", &x, &y); }
  20. void print() { printf("(%.2f %.2f)", x, y); }
  21. Point(double x = 0, double y = 0):x(x), y(y) {}
  22. };
  23. typedef Point Vector;
  24. Point operator + (const Point& A, const Point& B) {
  25. return Point(A.x + B.x, A.y + B.y);
  26. }
  27. Point operator - (const Point& A, const Point& B) {
  28. return Point(A.x - B.x, A.y - B.y);
  29. }
  30. Point operator * (const Point& A, double p) {
  31. return Point(A.x * p, A.y * p);
  32. }
  33. Point operator / (const Point& A, double p) {
  34. return Point(A.x / p, A.y / p);
  35. }
  36. bool operator < (const Point& A, const Point& B) {
  37. return A.x < B.x || (A.x == B.x && A.y < B.y);
  38. }
  39. bool operator == (const Point& A, const Point& B) {
  40. return A.x == B.x && A.y == B.y;
  41. }
  42. double Dot(const Vector& A, const Vector& B) {
  43. return A.x * B.x + A.y * B.y;
  44. }
  45. double Cross(const Vector& A, const Vector& B) {
  46. return A.x * B.y - A.y * B.x;
  47. }
  48. double TriangleArea(Point A, Point B, Point C) {
  49. return fabs(Cross(B-A, C-A)) / 2.0;
  50. }
  51. double Length(const Vector& A) {
  52. return sqrt(Dot(A, A));
  53. }
  54. double Angle(Vector A, Vector B) {
  55. return acos(Dot(A, B) / Length(A) / Length(B));
  56. }
  57. struct Line
  58. {
  59. Point p;
  60. Vector v;
  61. Line() {}
  62. Line(Point p, Vector v):p(p), v(v) {}
  63. Point point(double t) { return p + v * t; }
  64. };
  65. struct Circle
  66. {
  67. Point c;
  68. double r;
  69. };
  70. int getSegCircleIntersection(Line L, Circle C, vector<Point>& sol) {
  71. double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
  72. double e = a*a + c*c, f = 2*(a*b + c*d), g = b*b + d*d - C.r*C.r;
  73. double delta = f*f - 4*e*g;
  74. double t1, t2;
  75. int ans = 0;
  76. if(dcmp(delta) < 0) return 0;
  77. if(dcmp(delta) == 0) {
  78. t1 = t2 = -f / (2 * e);
  79. if(dcmp(t1) >= 0 && dcmp(t1 - 1) <= 0) {
  80. ans++;
  81. sol.push_back(L.point(t1));
  82. }
  83. return ans;
  84. }
  85. t1 = (-f - sqrt(delta)) / (2 * e);
  86. t2 = (-f + sqrt(delta)) / (2 * e);
  87. if(t1 > t2) swap(t1, t2);
  88. if(dcmp(t1) >= 0 && dcmp(t1 - 1) <= 0) {
  89. ans++;
  90. sol.push_back(L.point(t1));
  91. }
  92. if(dcmp(t2) >= 0 && dcmp(t2 - 1) <= 0) {
  93. ans++;
  94. sol.push_back(L.point(t2));
  95. }
  96. return ans;
  97. }
  98. bool inCircle(Circle C, Point p) {
  99. return dcmp(C.r - Length(C.c - p)) >= 0;
  100. }
  101. double IntersectionArea(Circle C, Point A, Point B) {
  102. Line L(A, B - A);
  103. int cnt = 0;
  104. bool inA, inB;
  105. if(inA = inCircle(C, A)) cnt++;
  106. if(inB = inCircle(C, B)) cnt++;
  107. if(cnt == 2) return TriangleArea(C.c, A, B);
  108. if(cnt == 1) {
  109. vector<Point> q;
  110. getSegCircleIntersection(L, C, q);
  111. if(inB) swap(A, B);
  112. double theta = Angle(q[0]-C.c, B-C.c);
  113. return C.r*C.r*theta/2 + TriangleArea(C.c, A, q[0]);
  114. }
  115. vector<Point> q;
  116. int sz = getSegCircleIntersection(L, C, q);
  117. if(sz <= 1) {
  118. double theta = Angle(A-C.c, B-C.c);
  119. return C.r*C.r*theta/2;
  120. }
  121. double theta = Angle(A-C.c, q[0]-C.c) + Angle(B-C.c, q[1]-C.c);
  122. return C.r*C.r*theta/2 + TriangleArea(q[0], q[1], C.c);
  123. }
  124. int n;
  125. double k;
  126. vector<Point> poly;
  127. Point A, B;
  128. Circle C;
  129. int main()
  130. {
  131. int kase = 1;
  132. while(scanf("%d%lf", &n, &k) == 2) {
  133. poly.resize(n);
  134. for(int i = 0; i < n; i++) poly[i].read();
  135. A.read(); B.read();
  136. poly.push_back(poly[0]);
  137. double D = 2.0 * (k*k*A.x-B.x) / (1.0-k*k);
  138. double E = 2.0 * (k*k*A.y-B.y) / (1.0-k*k);
  139. double F = (B.x*B.x+B.y*B.y-k*k*(A.x*A.x+A.y*A.y)) / (1.0-k*k);
  140. C.c = Point(-D/2.0, -E/2.0);
  141. C.r = sqrt(D*D+E*E-4.0*F) / 2.0;
  142. #ifdef DEBUG
  143. printf("Circle:");
  144. C.c.print();
  145. printf(" Radius : %.2f\n", C.r);
  146. #endif
  147. double ans = 0;
  148. for(int i = 0; i < n; i++) {
  149. int sign;
  150. if(dcmp(Cross(poly[i]-C.c, poly[i+1]-C.c)) > 0) sign = 1;
  151. else sign = -1;
  152. ans += sign * IntersectionArea(C, poly[i], poly[i+1]);
  153. }
  154. printf("Case %d: %.10f\n", kase++, fabs(ans));
  155. }
  156. return 0;
  157. }

LA 7072 Signal Interference 计算几何 圆与多边形的交的更多相关文章

  1. HDU 5130 Signal Interference(计算几何 + 模板)

    HDU 5130 Signal Interference(计算几何 + 模板) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5130 Descripti ...

  2. Gym - 101208J 2013 ACM-ICPC World Finals J.Pollution Solution 圆与多边形面积交

    题面 题意:给你一个半圆,和另一个多边形(可凹可凸),求面积交 题解:直接上板子,因为其实这个多边形不会穿过这个半圆,所以他和圆的交也就是和半圆的交 打的时候队友说凹的不行,不是板题,后面想想,圆与多 ...

  3. poj 3675 Telescope (圆与多边形面积交)

    3675 -- Telescope 再来一题.这题的代码还是继续完全不看模板重写的. 题意不解释了,反正就是一个单纯的圆与多边形的交面积. 这题的精度有点搞笑.我用比较高的精度来统计面积,居然wa了. ...

  4. HDU 5130 Signal Interference --计算几何,多边形与圆的交面积

    题意: 求所有满足PB <= k*PA 的P所在区域与多边形的交面积. 解法: 2014广州赛区的银牌题,当时竟然没发现是圆,然后就没做出来,然后就gg了. 圆的一般式方程: 设A(x1,y1) ...

  5. Hdu-2892 area 计算几何 圆与凸多边形面积交

    题面 题意:有一个凸多边形岛屿,然后告诉你从高空(x,y,h)投下炸弹,爆炸半径r,飞机水平速度和重力加速度,问岛屿被炸了多少 题解:算出来岛屿落地位置,再利用圆与凸多边形面积交 #include&l ...

  6. 简单几何(圆与多边形公共面积) UVALive 7072 Signal Interference (14广州D)

    题目传送门 题意:一个多边形,A点和B点,满足PB <= k * PA的P的范围与多边形的公共面积. 分析:这是个阿波罗尼斯圆.既然是圆,那么设圆的一般方程:(x + D/2) ^ 2 + (y ...

  7. HDU - 3982:Harry Potter and J.K.Rowling(半平面交+圆与多边形求交)(WA ing)

    pro:给定一枚蛋糕,蛋糕上某个位置有个草莓,寿星在上面切了N刀,最后寿星会吃含有草莓的那一块蛋糕,问他的蛋糕占总蛋糕的面积比. sol:显然需要半平面交求含有蛋糕的那一块,然后有圆弧,不太方便求交. ...

  8. Gym-100935I Farm 计算几何 圆和矩形面积交

    题面 题意:就是给你一个圆,和你一个矩形,求面积并,且 保证是一种情况:三角剖分后 一个点在圆内 两个在圆外 题解:可以直接上圆与凸多边形交的板子,也可以由这题实际情况,面积等于扇形减两个三角形 #i ...

  9. POJ3675 Telescope 圆和多边形的交

    POJ3675 用三角剖分可以轻松搞定,数据也小 随便AC. #include<iostream> #include<stdio.h> #include<stdlib.h ...

随机推荐

  1. 微信android手机中点击大图片会自动放大图片

    自己使用的是微信Android客户端,使用img标签的src属性将图片设置好了以后,在微信中调试,点击图片竟然放大,自己没写放大图片的方法,也没有调用wx.previewImage()方法,最后查找, ...

  2. 老技术,UrlRewriter实现全站伪静态

    看人家做淘宝客很火,就做了个网站.seo的话当然需要全站伪静态了,问了下空间商不支持mvc,尼玛,好吧,isapi_rewrite支持吗?“额,不支持!” -_-! 额,好吧,搬出n年前的东西了:微软 ...

  3. NOPI Excel 读取公式生成后的数据

    using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using S ...

  4. 【复习笔记】CSS基础

    外观 color:rgba(255,255,255,1),a表示alpha,透明度值0~1 font-family:字体1,字体2,字体3;确保某字体不存在时自动选择下一个,最好使用字体的英文名称保证 ...

  5. GoDaddy网站程序根目录 网站文件上传到虚拟主机哪个目录

    用的linux虚拟主机,网站根目录为public_html,(window主机的目录为httpdocs)我们需要把本地做好的网站上传到此目录下 cPanel控制面板 - 文件管理器 - public_ ...

  6. selenium+python之python多线程

    程序.进程及线程的区别 计算机程序是磁盘中可执行的二进制数据(或者其他类型)他们只有在被读取到内存中,被操作系统调用才开始他们的生命周期. 进程是程序的一次执行,每个进程都有自己的地址空间,内存,数据 ...

  7. Windows系统命令行下编译连接C/C++源代码方法

    Windows系统下编译连接源代码方法:cl -GX test.c-GX: 启动同步异常处理上面的命令会产生可执行程序:test.exe在命令行中直接输入:test.exe 就可运行该程序 Tips: ...

  8. iOS动画——Layer Animations

    我们先来看一下今天我们要实现的效果,今天实现的效果用第一篇View Animations能实现相同效果. 动画由书籍<iOS Animations by tutorials>提供,我只是一 ...

  9. [VC]关于ocx打包为cab的使用

    把打包的工具makecert.exe等放在c:/windows/system32/里才能在dos下面使用 注:如果本机使用可以codebase="http://localhost/testa ...

  10. [numpy] 基础练习 (一)

    Numpy常用总结 基础要打牢,恩. 基础 # 0 - 9 arr = np.arange(10) # 3*3 bool np.full((3,3),true,dtype = bool) np.one ...