D - Signal Interference
给定一个多边形及其内部的点A,并给出另一个点B,求多边形内部到B距离不超过到A距离的k倍的点集的面积。
经过推导可以得出来满足距离关系的点集是一个圆,那么就只需要求出这个圆之后求它与这个多边形的面积交即可。
H - Highway
某个人在距离高速公路D的点处,他在公路外的速度是v0, 公路上的速度是v1,求在时间T内能走到的区域的面积。
对于高速公路两侧的一个点,显然最快的方式是:
对于第一次到达高速公路的这个点,我们可以通过三分的方法来求出它。
这样实际的范围就是:
答案即为圆与这个六边形的面积交。六边形两端的顶点可以通过高速公路上最远的距离求出。圆的半径就是路外速度能走的最远距离。
不是很懂这是什么操作……一场区域赛两个计算几何都是圆与多边形面积交……很是奇葩……
H题:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
int sgn(double x)
{
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
return 1;
}
struct point
{
double x, y;
point (){}
point (double _x, double _y)
{
x = _x;
y = _y;
}
point operator - (const point &o) const
{
return point(x - o.x, y - o.y);
}
point operator + (const point &o) const
{
return point(x + o.x, y + o.y);
}
double operator ^ (const point &o) const
{
return x*o.y - y*o.x;
}
double operator * (const point &o) const
{
return x*o.x + y*o.y;
}
point operator * (const double &o) const
{
return point(x*o, y*o);
}
point operator / (const double &o) const
{
return point(x/o, y/o);
}
double dis(point o)
{
return sqrt((x-o.x)*(x-o.x) + (y-o.y)*(y-o.y));
}
double rad(point a, point b)
{
point p = *this;
return fabs(atan2(fabs((a-p)^(b-p)), (a-p)*(b-p)));
}
double len2()
{
return x*x + y*y;
}
point trunc(double r)
{
double l = sqrt(x*x + y*y);
if(!sgn(l)) return *this;
r /= l;
return point(x*r, y*r);
}
}A, B;
struct Line
{
point s, e;
Line (){}
Line (point _s, point _e)
{
s = _s;
e = _e;
}
point lineprog(point p)
{
return s + (((e-s)*((e-s)*(p-s)))/((e-s).len2()));
}
double dispointtoline(point p)
{
return fabs((p-s)^(e-s))/(s.dis(e));
}
};
struct circle
{
point p;
double r;
circle (){}
circle (point _p, double _r)
{
p = _p;
r = _r;
}
int relation(point b)
{
double dst = b.dis(p);
if(sgn(dst - r) < 0) return 2;
else if(sgn(dst - r) == 0) return 1;
return 0;
}
int relationline(Line v)
{
double dst = v.dispointtoline(p);
if(sgn(dst - r) < 0) return 2;
else if(sgn(dst - r) == 0) return 1;
return 0;
}
int pointcrossline(Line v, point &p1, point &p2)
{
if(!(*this).relationline(v)) return 0;
point a = v.lineprog(p);
double d = v.dispointtoline(p);
d = sqrt(r*r - d*d);
if(sgn(d) == 0)
{
p1 = a;
p2 = a;
return 1;
}
p1 = a + (v.e - v.s).trunc(d);
p2 = a - (v.e - v.s).trunc(d);
return 2;
}
double areatan(point a, point b)
{
if(sgn((p-a)^(p-b)) == 0) return 0.0;
point q[5];
int len = 0;
q[len++] = a;
Line l(a, b);
point p1, p2;
if(pointcrossline(l, q[1], q[2]) == 2)
{
if(sgn((a-q[1])*(b-q[1]))< 0)q[len++] = q[1];
if(sgn((a-q[2])*(b-q[2]))< 0)q[len++] = q[2];
}
q[len++] = b;
if(len == 4 && sgn((q[0]-q[1])*(q[2]-q[1])) > 0) swap(q[1], q[2]);
double res = 0;
for(int i = 0;i < len-1;i++)
{
if(relation(q[i]) == 0 || relation(q[i+1]) == 0)
{
double arg = p.rad(q[i], q[i+1]);
res += r*r*arg/2.0;
}
else res += fabs((q[i]-p)^(q[i+1]-p))/2.0;
}
return res;
}
};
struct polygon
{
int n;
point p[505];
double areacircle(circle c)
{
double ans = 0;
for(int i = 0;i < n;i++)
{
int j = (i+1) % n;
if(sgn((p[j]-c.p)^(p[i]-c.p)) >= 0)
ans += c.areatan(p[i], p[j]);
else ans -= c.areatan(p[i], p[j]);
}
return fabs(ans);
}
}POL;
double v0, v1, D, T;
double fun(double x)
{
return sqrt(v0*x*v0*x - D*D) + v1*(T - x);
}
int main()
{
int kase = 0;
while(scanf("%lf%lf%lf%lf", &v0, &v1, &D, &T) != EOF)
{
POL.n = 6;
circle C;
C.p.x = 0, C.p.y = D, C.r = v0*T;
double L = D/v0, R = T, mid, mmid;
for(int i = 1;i <= 100;i++)
{
mid = (L + R)/2;
mmid = (mid + R)/2;
double fa = fun(mid), fb = fun(mmid);
if(fa > fb) R = mmid;
else L = mid;
}
double t = (L + R)/2;
double x = fun(t);
double ya = T/t*D, xa = sqrt(v0*T*v0*T - ya*ya);
ya -= D;
POL.p[0] = point(x, 0);
POL.p[1] = point(xa, ya);
POL.p[2] = point(-xa, ya);
POL.p[3] = point(-x, 0);
POL.p[4] = point(-xa, -ya);
POL.p[5] = point(xa, -ya);
double ans = pi*v0*T*v0*T + xa*ya*4 + ya*(x - xa)*2;
ans -= POL.areacircle(C);
if(v0*T <= D) ans = pi*v0*T*v0*T;
printf("Case %d: %.8lf\n", ++kase, ans);
}
return 0;
}