HDU 5130 & 5134 2014ICPC广州现场赛 D & H (计算几何)

2014GZ - D  & 2014GZ - H

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;
}

猜你喜欢

转载自blog.csdn.net/NPU_SXY/article/details/82990083