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;
    }
  • 相关阅读:
    YII框架实现排序
    YII2 实现登录时候修改最新登录时间
    YII框架下实现密码修改
    json在PHP中应用技巧
    更换Python pip库镜像地址
    Python3创建RIDE桌面快捷方式的另一种方法
    谈谈测试人员的基本素养
    《微软的软件测试之道》阅读笔记
    PPT如何一页多张打印且铺满整个页面
    Linux 在线模拟器
  • 原文地址:https://www.cnblogs.com/1carus/p/3329812.html
Copyright © 2011-2022 走看看