第一次见到这种题,有想法,不会打。。。
代码太长了,有几个链接不错
http://www.xuebuyuan.com/1749999.html //个人认为这个讲的最详细
http://blog.youkuaiyun.com/ch2010091/article/details/7786450
ac代码:
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const int maxn = 100000 + 10;
const double eps = 1e-10;
typedef struct _point
{
double x,y;
_point (double x = 0, double y = 0):x(x),y(y) {}
}Point,Vector;
Point p[maxn];
typedef struct _circle
{
Point c;
double r;
}Circle;
typedef struct _line
{
Point p;
Vector v;
}Line;
Vector operator + (Vector a, Vector b) {return Vector(a.x + b.x, a.y + b.y);}
Vector operator - (Vector a, Vector b) {return Vector(a.x - b.x, a.y - b.y);}
double Dot (Vector a, Vector b) {return a.x * b.x + a.y * b.y;}
double Length (Vector a) {return sqrt (Dot (a, a));}
double Cross (Vector a, Vector b) {return a.x * b.y - a.y * b.x;}
double Distance (Point a, Point b) {return Length (a - b);}
double Angle (Vector a, Vector b) {return acos (Dot (a, b) / Length (a) / Length (b));}
int dcmp (double x)
{
if (fabs (x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
int getLineCircleIntersection (Line L, Circle C, double& t1, double& t2)
{//返回线段和圆的交点个数
double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
double e = a * a + c * c, f = 2 * (a * b + c * d), g = b * b + d * d - C.r * C.r;
double delta = f * f - 4 * e * g; //判别式
if (dcmp (delta) < 0) return 0;
if (dcmp (delta) == 0)
{
t1 = t2 = -f / (2 * e);
return 1;
}
t1 = (-f - sqrt (delta)) / (2 * e);
t2 = (-f + sqrt (delta)) / (2 * e);
return 2;
}
double slove (Circle r, int n)
{
int i,j;
double ans = 0;
double x;
for (i = 0; i < n; i++)
{
if (dcmp(Distance(p[i], r.c) - r.r) <= 0 && dcmp(Distance(p[(i + 1) % n], r.c) - r.r) <= 0)
{//两个顶点都在圆内,直接求三角形面积
ans += Cross (p[i] - r.c, p[(i + 1) % n] - r.c) / 2;
}
else if (dcmp(Distance(p[i], r.c) - r.r) <= 0 && dcmp(Distance(p[(i + 1) % n], r.c) - r.r) > 0)
{//p[i]在圆内,p[i+1]在圆外,求与圆的交点
double t1,t2;
Line L;
L.p = p[i];
L.v = p[(i + 1) % n] - p[i];
getLineCircleIntersection (L, r, t1, t2);
t1 = t1 > 0 ? t1 : t2;
Point inter;
inter.x = L.p.x + L.v.x * t1; inter.y = L.p.y + L.v.y * t1;
ans += Cross (p[i] - r.c, inter - r.c) / 2; //三角形面积
x = (Angle (inter - r.c, p[(i + 1) % n] - r.c) / 2.0) * r.r * r.r; //扇形面积
if (Cross (inter - r.c, p[(i + 1) % n] - r.c) < 0)
ans -= x;
else
ans += x;
}
else if (dcmp(Distance(p[i], r.c) - r.r) > 0 && dcmp(Distance(p[(i + 1) % n], r.c) - r.r) <= 0)
{//p[i]在圆外,p[i+1]在圆内
double t1,t2;
Line L;
L.p = p[i];
L.v = p[(i + 1) % n] - p[i];
getLineCircleIntersection (L, r, t1, t2);
t1 = t1 < t2 ? t1 : t2;
Point inter;
inter.x = L.p.x + L.v.x * t1; inter.y = L.p.y + L.v.y * t1;
ans += Cross (inter - r.c, p[(i + 1) % n] - r.c) / 2; //三角形面积
x = (Angle (p[i] - r.c, inter - r.c) / 2.0) * r.r * r.r; //扇形面积
if (Cross (p[i] - r.c, inter - r.c) < 0)
ans -= x;
else
ans += x;
}
else if (dcmp(Distance(p[i], r.c) - r.r) > 0 && dcmp(Distance(p[(i + 1) % n], r.c) - r.r) > 0)
{//两个点都在圆外
double t1,t2;
Line L;
L.p = p[i];
L.v = p[(i + 1) % n] - p[i];
if (getLineCircleIntersection (L, r, t1, t2) <= 1)
{//只有一个或者没有交点
x = (Angle (p[(i + 1) % n] - r.c, p[i] - r.c) / 2.0) * r.r * r.r; //扇形面积
if (Cross (p[i] - r.c, p[(i + 1) % n] - r.c) < 0)
ans -= x;
else
ans += x;
}
else
{
Point inter1,inter2;
if (t1 > t2)
swap (t1,t2);
inter1.x = L.p.x + L.v.x * t1; inter1.y = L.p.y + L.v.y * t1;
inter2.x = L.p.x + L.v.x * t2; inter2.y = L.p.y + L.v.y * t2;
ans += Cross (inter1 - r.c, inter2 - r.c) / 2; //三角形面积
x = (Angle (p[i] - r.c, inter1 - r.c) / 2.0) * r.r * r.r; //扇形面积
if (Cross (p[i] - r.c, inter1 - r.c) < 0)
ans -= x;
else
ans += x;
x = (Angle (inter2 - r.c, p[(i + 1) % n] - r.c) / 2.0) * r.r * r.r;
if (Cross (inter2 - r.c, p[(i + 1) % n] - r.c) < 0)
ans -= x;
else
ans += x;
}
}
}
return ans;
}
int main ()
{
double h;
Circle c;
while (scanf ("%lf%lf%lf",&c.c.x, &c.c.y, &h) != EOF)
{
double x1,y1;
scanf ("%lf%lf",&x1, &y1);
//求圆心
double t = sqrt (h / 5.0);
c.c.x += x1 * t;
c.c.y += y1 * t;
scanf ("%lf",&c.r);
int n;
scanf ("%d",&n);
int i,j;
for (i = 0; i < n; i++)
{
scanf ("%lf%lf",&p[i].x,&p[i].y);
}
printf ("%.2lf\n",fabs (slove (c, n)));
}
return 0;
}