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;
}
原文地址:https://www.cnblogs.com/1carus/p/3329812.html