zoukankan      html  css  js  c++  java
  • USACO 3.4.1 Closed Fences

    刚开始试着连一下,对于没有任何遮挡的线段,连接观察点和他的中点,如果没有阻挡,那么肯定就能看见啦

    对于有遮挡的呢,我们可以试一下连接遮挡他的遮挡线段的端点,发现好像有点意思,如果射线能跟他严格相交,并且射线在另一面没有被夹住的话,就是可以看见的

    于是有了算法,连接端点和所有中点。怎么编程呢,发现可以设一个mr表示如果射线右边有端点交于射线的最小距离,ml同理,mm表示于射线严格相交的最近的一个点,我们发现,如果mm不存在,或者射线被2端夹住了(ml<mm&&mr<mm)就不行了。。有木有特殊情况呢。。木有,都被排除了。而且这样mm好像也把中点问题解决了。

    (嘛。。。相当于你通过一个边缘刚好看见一个物体,你怎么才算能看见呢,视角可以往那边移一点,但是如果那边又有一个边缘夹住了视角,就只是一条缝,当然看不见了)

    代码就可以这样写(以下代码是参考。自认为写的很恶心)

    # include <cstdio>
    # include <iostream>
    # include <algorithm>
    # include <cfloat>
    # include <cmath>
    using namespace std;
    int n,cansee[300];
    double ox,oy,x[300],y[300],eps = 1e-6;
    struct Point{
        double x,y;
        Point (double x,double y):x(x),y(y) {}    
    };
    int online(Point p1,Point p2,Point p3)
    {
        return (p1.x<max(p2.x,p3.x)&&p1.x>min(p2.x,p3.x)&&p1.y>min(p2.y,p3.y)&&p1.y<max(p2.y,p3.y));
    }
    double f(Point p1,Point p2,Point p3)
    {
        return (p3.x-p2.x)*(p1.y-p2.y) - (p3.y-p2.y)*(p1.x-p2.x);
    }
    int ff(Point p1,Point p2,Point p3,Point p4)
    {
        double d1 = f(p1,p3,p4); double d2 = f(p2,p3,p4);
        double d3 = f(p3,p1,p2); double d4 = f(p4,p1,p2);
        if (d1*d2<0&&d3*d4<0) return 1;
        if (fabs(d1)<eps&&online(p1,p3,p4)) return 1;
        if (fabs(d2)<eps&&online(p2,p3,p4)) return 1;
        if (fabs(d3)<eps&&online(p3,p1,p2)) return 1;
        if (fabs(d4)<eps&&online(p4,p1,p2)) return 1;
        return 0;
    }
    double dist(double a1,double b1)
    {
        return sqrt((ox-a1)*(ox-a1)+(oy-b1)*(oy-b1));
    }
    int judge(double ix,double iy,double x1,double y1,double xp,double yp)
    {
        if ((((ix-ox)*(x1)+(iy-oy)*(y1))/(dist(ix,iy)*dist(xp,yp))>eps)) return 1;
        return 0;
    }
    int ifcansee(double xp,double yp)
    {
        double mr=DBL_MAX,ml=DBL_MAX,mm=DBL_MAX;
        Point p1(ox,oy),p2(xp,yp);
        int res;
        double x1 = xp-ox,y1 = yp-oy;
        double a1 = y1,b1 = -x1,c1 = a1*ox+b1*oy;
        for (int i=0;i<n;++i)
        {
            Point p3(x[i],y[i]),p4(x[i+1],y[i+1]);
            double x2 = x[i+1]-x[i],y2 = y[i+1]-y[i];
            double a2 = y2,b2 = -x2,c2 = a2*x[i]+b2*y[i];
            double cross = a1*b2-a2*b1;
            if (fabs(cross)<eps) continue;
            double d1 = f(p3,p1,p2),d2 = f(p4,p1,p2);
            if (d1*d2<0)
            {
                double ix = (b2*c1-b1*c2)/cross,iy = (a1*c2-a2*c1)/cross;
                if (judge(ix,iy,x1,y1,xp,yp))
                {
                    double len = dist(ix,iy);
                    if (len<mm)
                    {
                        mm = len;
                        res = i+1;
                    }    
                }
            }
            if (fabs(d1)<eps&&judge(p3.x,p3.y,x1,y1,xp,yp)&&d2>0)
                mr = min(mr,dist(p3.x,p3.y));
            if (fabs(d2)<eps&&judge(p4.x,p4.y,x1,y1,xp,yp)&&d1>0)
                mr = min(mr,dist(p4.x,p4.y));
            if (fabs(d2)<eps&&judge(p4.x,p4.y,x1,y1,xp,yp)&&d1<0)
                ml = min(ml,dist(p4.x,p4.y));
            if (fabs(d1)<eps&&judge(p3.x,p3.y,x1,y1,xp,yp)&&d2<0)
                ml = min(ml,dist(p3.x,p3.y));    
        }
        if (mm==DBL_MAX||(mr<mm&&ml<mm))
            return -1;
        return res;
    }
    int main()
    {
        freopen("fence4.in","r",stdin);
        freopen("fence4.out","w",stdout);
        int i,j,t,ans=0;
        cin>>n>>ox>>oy;
        for (i=0;i<n;++i)
            cin>>x[i]>>y[i];
        x[n] = x[0]; y[n] = y[0];
        for (i=0;i<n;++i)
            for (j=0;j<n;++j)
            {
                if (j==i) continue;
                Point P1(x[i],y[i]); Point P2(x[i+1],y[i+1]);
                Point P3(x[j],y[j]); Point P4(x[j+1],y[j+1]);
                if (ff(P1,P2,P3,P4))
                {
                    cout<<"NOFENCE"<<endl;
                    return 0;
                }
            }
        for (i=0;i<n;++i)
        {
            t = ifcansee(x[i],y[i]);
            if (t!=-1) cansee[t] = 1;
            t = ifcansee((x[i]+x[i+1])/2.0,(y[i]+y[i+1])/2.0);
            if (t!=-1) cansee[t] = 1;
        }
        for (i=1;i<=n;++i)
            if (cansee[i])
                ans++;
        cout<<ans<<endl;
        for (i=1;i<n-1;++i)
            if (cansee[i])
                cout<<x[i-1]<<" "<<y[i-1]<<" "<<x[i]<<" "<<y[i]<<endl;    
        if (cansee[n]) cout<<x[0]<<" "<<y[0]<<" "<<x[n-1]<<" "<<y[n-1]<<endl;
        if (cansee[n-1]) cout<<x[n-2]<<" "<<y[n-2]<<" "<<x[n-1]<<" "<<y[n-1]<<endl;
        return 0;
    }
  • 相关阅读:
    关于求 p_i != i and p_i != i+1 的方案数的思考过程
    poj 3041 Asteroids 二分图最小覆盖点
    poj 1325 Machine Schedule 最小顶点覆盖
    poj 1011 Sticks 减枝搜索
    poj 1469 COURSES 最大匹配
    zoj 1516 Uncle Tom's Inherited Land 最大独立边集合(最大匹配)
    Path Cover (路径覆盖)
    hdu 3530 SubSequence TwoPoint单调队列维护最值
    zoj 1654 Place the Rebots 最大独立集转换成二分图最大独立边(最大匹配)
    poj 1466 Girls and Boys 二分图最大独立子集
  • 原文地址:https://www.cnblogs.com/1carus/p/3329812.html
Copyright © 2011-2022 走看看