zoukankan      html  css  js  c++  java
  • [USACO 6.5.2]Closed Fences

    题目大意

      求从一点出发的可视线段.

    题解

      先找出没有"被覆盖的点",然后从视点出发和每个可视点连线形成一条矢量线段,然后和每条线段的是否有有交点.

      然后也有很多特殊情况需要处理..这里不再赘述.详情请见代码

    代码

    /*
    TASK:fence4
    LANG:C++
    */
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    struct Vector
    {
        double x, y;
        
        Vector(double x=0, double y=0) : x(x), y(y)
        {
        }
        
        Vector operator + (Vector rbs)
        {
            return Vector(x + rbs.x, y + rbs.y);
        }
        
        Vector operator - (Vector rbs)
        {
            return Vector(x - rbs.x, y - rbs.y);
        }
        
        Vector operator * (double vari)
        {
            return Vector(x * vari, y * vari);
        }
        
    }v[205], per;
    
    const double eps = 1e-10;
    int dcmp(double x)
    {
        if (fabs(x) < eps) return 0;
        else return x < 0 ? -1 : 1;
    }
    
    double cross(Vector A, Vector B)
    {
        return A.x * B.y - A.y * B.x;
    }
    
    bool judge(Vector a1, Vector a2, Vector b1, Vector b2)
    {
        double c1 = cross(a2 - a1, b1 - a1), c2 = cross(a2 - a1, b2 - a1);
        double c3 = cross(b2 - b1, a1 - b1), c4 = cross(b2 - b1, a2 - b1);
        return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
    }
    
    bool judge2(Vector a1, Vector a2, Vector b1, Vector b2)
    {
        double c1 = cross(a2 - a1, b1 - a1), c2 = cross(a2 - a1, b2 - a1);
        return dcmp(c1) * dcmp(c2) < 0;
    }
    
    Vector getv(Vector P, Vector v, Vector Q, Vector w)
    {
        Vector u = P - Q;
        double t = cross(w, u) / cross(v, w);
        return P + (v * t);
    }
    
    double sqr(double x)
    {
        return x * x;
    }
    
    double dist(Vector a, Vector b)
    {
        return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
    }
    
    int n, ansn, ans[205][2];
    double mindis[205];
    bool coverv[205];
    
    int main()
    {
        freopen("fence4.in", "r", stdin);
        freopen("fence4.out", "w", stdout);
        scanf("%d", &n);
        scanf("%lf%lf", &per.x, &per.y);
        for (int i = 0; i < n; ++i) scanf("%lf%lf", &v[i].x, &v[i].y);
        bool flag = true;
        for (int i = 0; i < n; ++i)
        {
            for (int j = i + 2; j < n; ++j)
                if (judge(v[i], v[(i+1) % n], v[j], v[(j+1) % n]))
                {
                    flag = false;
                    break;
                }
            if (!flag) break;
        }
        if (!flag) printf("NOFENCE
    ");
        else
        {
            for (int i = 0; i < n; ++i) mindis[i] = 1e20;
            memset(coverv, false, sizeof(coverv));
            for (int i = 0; i < n; ++i)
            {
                for (int j = 0; j < n; ++j)
                {
                    if (j != i && j+1 != i)
                    {
                        if (judge2(per, v[i], v[j], v[(j+1) % n]))
                        {
                            Vector tmpv = getv(per, per-v[i], v[j], v[j]-v[(j+1) % n]);
                            if (dcmp(tmpv.x-per.x) * dcmp(v[i].x-per.x) < 0 || dcmp(tmpv.y-per.y) * dcmp(v[i].y-per.y) < 0) continue;
                            mindis[i] = min(mindis[i], dist(per, tmpv));
                        }
                    }
                    if (i != j && cross(v[i]-per, v[j]-per) == 0)
                    {
                        if (dcmp(v[j].x-per.x) * dcmp(v[i].x-per.x) < 0 || dcmp(v[j].y-per.y) * dcmp(v[i].y-per.y) < 0) continue;
                        if (dist(v[i], per) < dist(v[j], per)) coverv[j] = true;
                        else coverv[i] = true;
                    }
                }
            }
            ansn = 0;
            for (int i = 0; i < n; ++i)
            {
                if (cross(v[i] - per, v[(i+1) % n] - per) == 0) continue;
                double d1 = dist(per, v[i]), d2 = dist(per, v[(i+1) % n]);
                int j = i;
                bool canbeseen = true;
                if (d1 > mindis[j] || coverv[j])
                {
                    for (;;)
                    {
                        if (j == -1) j = n - 1;
                        if (j == (i+1) % n)
                        {
                            canbeseen = false;
                            break;
                        }
                        if (!coverv[j])
                        {
                            int left = (j-1+n)%n, right = (j+1)%n;
                            if (dcmp(cross(v[j]-per, v[left]-per)) * dcmp(cross(v[j]-per, v[right]-per)) > 0)
                                if (judge2(per, v[j], v[i], v[(i+1) % n]))
                                {
                                    Vector tmpv = getv(per, per-v[j], v[i], v[i]-v[(i+1) % n]);
                                    if (abs(mindis[j] - dist(per, tmpv)) < eps) break;
                                }
                        }
                        j--;
                    }
                }
                int tmp = j;
                j = (i+1) % n;
                if (d2 > mindis[j] || coverv[j])
                {
                    for (;;)
                    {
                        if (j == n) j = 0;
                        if (j == i)
                        {
                            canbeseen = false;
                            break;
                        }
                        if (!coverv[j])
                        {
                            int left = (j-1+n)%n, right = (j+1)%n;
                            if (dcmp(cross(v[j]-per, v[left]-per)) * dcmp(cross(v[j]-per, v[right]-per)) > 0)
                                if (judge2(per, v[j], v[i], v[(i+1) % n]))
                                {
                                    Vector tmpv = getv(per, per-v[j], v[i], v[i]-v[(i+1) % n]);
                                    if (abs(mindis[j] - dist(per, tmpv)) < eps) break;
                                }
                        }
                        j++;
                    }
                }
                if (canbeseen && (cross(v[tmp] - per, v[j] - per) != 0))
                {
                    ans[ansn][0] = i;
                    ans[ansn][1] = (i+1) % n;
                    if (ans[ansn][1] < ans[ansn][0]) swap(ans[ansn][0], ans[ansn][1]);
                    j = ansn;
                    ansn++;
                    while (j != 0 && ans[j][1] == ans[j-1][1] && ans[j][0] < ans[j-1][0])
                    {
                        swap(ans[j][0], ans[j-1][0]);
                        swap(ans[j][1], ans[j-1][1]);
                        j--;
                    }
                }
            }
            printf("%d
    ", ansn);
            for (int i = 0; i < ansn; ++i)
                printf("%.0lf %.0lf %.0lf %.0lf
    ", v[ans[i][0]].x, v[ans[i][0]].y, v[ans[i][1]].x, v[ans[i][1]].y);
        }
        return 0;
    }
  • 相关阅读:
    Note/Solution 转置原理 & 多点求值
    Note/Solution 「洛谷 P5158」「模板」多项式快速插值
    Solution 「CTS 2019」「洛谷 P5404」氪金手游
    Solution 「CEOI 2017」「洛谷 P4654」Mousetrap
    Solution Set Border Theory
    Solution Set Stirling 数相关杂题
    Solution 「CEOI 2006」「洛谷 P5974」ANTENNA
    Solution 「ZJOI 2013」「洛谷 P3337」防守战线
    Solution 「CF 923E」Perpetual Subtraction
    KVM虚拟化
  • 原文地址:https://www.cnblogs.com/albert7xie/p/6343751.html
Copyright © 2011-2022 走看看