HDOJ 5134 Highway

#include <iostream>
#include <queue> 
#include <stack> 
#include <map> 
#include <set> 
#include <bitset> 
#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 1005
#define maxm 2000005
#define eps 1e-10
#define mod 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

int sgn(double x)
{
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    else return 1;
}

struct Point
{
    double x, y;
    Point() {}
    Point(double _x, double _y) {
        x = _x;
        y = _y;
    }
    bool operator == (Point b) const {
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
    }
    bool operator < (Point b) const {
        return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
    }
    Point operator - (const Point &b) const {
        return Point(x - b.x, y - b.y);
    }
    double operator ^ (const Point &b) const {
        return x * b.y - y * b.x;
    }
    double operator * (const Point &b) const {
        return x * b.x + y * b.y;
    }
    double len(void)
    {
        return hypot(x, y);
    }
    double len2(void)
    {
        return x * x + y * y;
    }
    double distance(Point p)
    {
        return hypot(x - p.x, y - p.y);
    }
    Point operator + (const Point &b) const {
        return Point(x + b.x, y + b.y);
    }
    Point operator * (const double &k) const {
        return Point(x * k, y * k);
    }
    Point operator / (const double &k) const {
        return Point(x / k, y / k);
    }
    double rad(Point a, Point b) {
        Point p = *this;
        return fabs(atan2(fabs((a - p) ^ (b - p)), (a - p) * (b - p)));
    }
    Point trunc(double r) {
        double l = len();
        if(!sgn(l)) return *this;
        r /= l;
        return Point(x * r, y * r);
    }
    void input(void)
    {
        scanf("%lf%lf", &x, &y);
    }
    Point rotleft(void)
    {
        return Point(-y, x);
    }
    Point rotright(void)
    {
        return Point(y, -x);
    }
};

struct Line
{
    Point s, e;
    Line() {}
    Line(Point _s, Point _e) {
        s = _s;
        e = _e;
    }
    double length(void)
    {
        return s.distance(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)) / length();
    }
};

struct circle
{
    Point p;
    double r;
    circle() {}
    circle(Point _p, double _r) {
        p = _p;
        r = _r;
    }
    circle(double x, double y, double _r) {
        p = Point(x, y);
        r = _r;
    }

    int relation(Point b)
    {
        double dst = b.distance(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 areatriangle(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;
    }

    int tangentline(Point q, Line &u, Line &v) {
        int x = relation(q);
        if(x == 2) return 0;
        if(x == 1) {
            u = Line(q, q + (q - p).rotleft());
            v = u;
            return 1;
        }
        double d = p.distance(q);
        double l = r * r / d;
        double h = sqrt(r *r - l * l);
        u = Line(q, p + ((q - p).trunc(l) + (q - p).rotleft().trunc(h)));
        v = Line(q, p + ((q - p).trunc(l) + (q - p).rotright().trunc(h)));
        return 2;
    }
};

struct polygon
{
    int n;
    Point p[maxn];
    Line l[maxn];
    void input(int _n)
    {
        n = _n;
        for(int i = 0; i < n;  i++)
            p[i].input();
    }
    void getline(void)
    {
        for(int i = 0; i < n; i++)
            l[i] = Line(p[i], p[(i+1) % n]);
    }
    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.areatriangle(p[i], p[j]);
            else ans -= c.areatriangle(p[i], p[j]);
        }
        return fabs(ans);
    }
    double getarea(void)
    {
        double sum = 0;
        for(int i = 0; i < n; i++) {
            sum += (p[i] ^ p[(i+1) % n]);
        }
        return fabs(sum) / 2;
    }
};

polygon poly;
circle c;
double v0, v1, d, t;

Point pp;
circle test;
Line u, v;
double mx;

double calc(double x)
{
    double t2 = t - sqrt(d * d + x * x) / v0;
    return t2 * v1 + x;
}

double find(void)
{
    double bot = 0, top = v1 * t, mid1, mid2;
    while(top - bot > eps) {
        mid1 = bot + (top - bot) / 3;
        mid2 = bot + (top - bot) / 3 * 2;
        if(calc(mid1) > calc(mid2)) top = mid2;
        else bot = mid1;
    }
    return mid1;
}

void work(void)
{
    double ans = PI * (v0 * t) * (v0 * t);
    if(sgn(v0 * t - d) <= 0) {
        printf("%.9f\n", ans);
        return;
    }
    c = circle(Point(0.0, 0.0), v0 * t);
    double pos = find();
    double mx = calc(pos);
    test = circle(Point(pos, d), (t - sqrt(d * d + pos * pos) / v0) * v0);
    pp = Point(mx, d);
    int temp = test.tangentline(pp, u, v);
    double tmp = mx * abs(u.e.y - u.s.y) / abs(u.e.x - u.s.x);
    poly.p[0] = u.e;
    poly.p[1] = Point(mx, d);
    poly.p[2] = v.e;
    poly.n = 3;
    poly.getline();
    ans += 2 * poly.getarea();
    ans -= 2 * poly.areacircle(c);
    printf("%.9f\n", ans);
}

int main(void)
{
    int _ = 0;
    while(scanf("%lf%lf%lf%lf", &v0, &v1, &d, &t)!=EOF) {
        printf("Case %d: ", ++_);
        work();
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值