1. 程式人生 > >HDU 5130 & 5134 2014ICPC廣州現場賽 D & H (計算幾何)

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