zoukankan      html  css  js  c++  java
  • 【BZOJ 1020】 [SHOI2008]安全的航线flight

    【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1020

    【题意】

    【题解】

    二分+判断点是否在多边形区域内+计算点到直线的最短距离
    对于每条线段,假设这条线段为(x,y)首先将线段的两段尝试更新距离陆地距离最近的距离中最远的距离ans,并求出其在陆地上对应的点u和v;(如果x和y都在陆地上那么u、v就都是陆地上的点)
    然后在这条(x,y)中找一个点mid
    使得pv=pu;
    然后先用p点尝试更新一下答案ans(找离p点最近的陆地上的点)
    然后如果pv< ans,那么这条直线就不用再找了;
    因为如果是(x,y)上异于p的点;
    它里陆地的距离只会比pv更近.
    (画图就知道了);
    这其实就只是用中点去剪枝而已.
    但效果很好.
    如果不满足pv< ans
    则把xp和py两条直线再进行处理就好;
    写个循环队列咯。

    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%lld",&x)
    #define red(x) scanf("%lf",&x)
    
    typedef pair<int, int> pii;
    typedef pair<LL, LL> pll;
    
    const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };
    const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };
    const double pi = acos(-1.0);
    const int N = 40;
    const int M = 100e4 + 10;
    const double eps = 1e-4;
    
    struct point
    {
        double x, y;
    };
    
    point operator -(point u, point v) {
        point t; t.x = u.x - v.x; t.y = u.y - v.y; return t;
    }
    
    struct abc
    {
        point p1, p2;
    };
    double crs(point u, point v) { return u.x*v.y - u.y*v.x; }
    bool upon(point u, point v, point w) {
        return !crs(v - u, w - u) && (u.x - v.x)*(u.x - w.x) <= 0 && (u.y - v.y)*(u.y - w.y) <= 0;
    }
    bool havitr(point u, point v, point s, point t) {
        return crs(v - u, s - u)*crs(v - u, t - u) <= 0 && crs(t - s, u - s)*crs(t - s, v - s) <= 0;
    }
    struct disp { point p; double dis; };
    double dot(point u, point v) { return u.x*v.x + u.y*v.y; }
    double dist(point u, point v) { return sqrt(dot(u - v, u - v)); }
    disp lss(disp u, disp v) { return (u.dis<v.dis) ? u : v; }
    
    point getitr(point u, point s, point v, point t) {
        double tmp = crs(t, u - v) / crs(s, t);
        u.x += s.x*tmp; u.y += s.y*tmp; return u;
    }
    
    point s;
    
    struct land
    {
        int tot;
        point p[N];
        void init()
        {
            rei(tot);
            rep1(i, 1, tot)
                red(p[i].x), red(p[i].y);
            p[tot + 1] = p[1];
        }
        bool inside(point t)
        {
            int i, sum = 0;
            for (i = 1; i <= tot; i++)
                if (upon(t, p[i], p[i + 1])) return 1;
            t.y += 0.1;
            s.y = t.y; s.x = -10001;
            for (i = 1; i <= tot; i++)
                if (havitr(s, t, p[i], p[i + 1])) sum++;
            t.y -= 0.1;
            return sum & 1;
        }
    };
    
    int c, n;
    double ans = 0;
    point a[N];
    abc q[M];
    land b[N];
    
    disp nearst(point u, point v, point w) {
        disp t;
        if (v.x == w.x && v.y == w.y) t.p = v; else
            if (dot(u - v, w - v) <= 0) t.p = v; else
                if (dot(u - w, v - w) <= 0) t.p = w; else {
                    point s = v - w; swap(s.x, s.y); s.x = -s.x;
                    t.p = getitr(u, s, v, w - v);
                }
        t.dis = dist(t.p, u); return t;
    }
    
    point updata(point t)
    {
        rep1(i, 1, c)
            if (b[i].inside(t))
                return t;
        disp temp;
        temp.dis = 1e20;
        rep1(i, 1, c)
            rep1(j, 1, b[i].tot)
            temp = lss(temp, nearst(t, b[i].p[j], b[i].p[j + 1]));
        ans = max(ans, temp.dis);
        return temp.p;
    }
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        rei(c), rei(n);
        rep1(i, 1, n)
        {
            red(a[i].x), red(a[i].y);
        }
        rep1(i, 1, c)
            b[i].init();
        int head = 0, tail = 0;
        rep1(i, 1, n - 1)
        {
            q[++tail].p1 = a[i], q[tail].p2 = a[i + 1];
            updata(a[i]);
        }
        while (head != tail)
        {
            head = head%M + 1;
            point x = q[head].p1, y = q[head].p2;
            point u = updata(x), v = updata(y),mid;
            while (dist(x, y) > eps)
            {
                mid.x = (x.x + y.x) / 2, mid.y = (x.y + y.y) / 2;
                if (dist(u, mid) < dist(v, mid))
                    x = mid;
                else
                    y = mid;
            }
            double temp = dist(u, x); updata(x);
            if (temp > ans+eps)
            {
                tail = tail%M + 1, q[tail].p1 = q[head].p1, q[tail].p2 = mid;
                tail = tail%M + 1, q[tail].p1 = mid, q[tail].p2 = q[head].p2;
            }
        }
        printf("%.2f
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    记录一则enq: TX
    RAC节点两边存储名字不一致导致的故障及相关延伸
    记录一则fsck的简单案例
    RAC某节点v$asm_disk查询hang分析处理
    统计信息自动收集任务失效原因排查
    OEMCC 13.2 安装部署
    Linux平台Oracle 12.1.0.2 单实例安装部署
    java 除法运算只保留整数位的4种方式
    eclipse spring 配置文件xml校验时,xsd报错
    oracle decode()函数的参数原来可以为sql语句!
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626569.html
Copyright © 2011-2022 走看看