【USACO 3.4】(fence4)Closed Fences

A closed fence in the plane is a set of non-crossing, connected line segments with N corners (3 < N < 200). The corners or vertices are each distinct and are listed in counter-clockwise order in an array {xi, yi}, i in (1..N).

Every pair of adjacent vertices defines a side of the fence. Thus {xi yi xi+1 yi+1} is a side of the fence for all i in (1..N). For our purposes, N+1 = 1, so that the first and last vertices making the fence closed.

Here is a typical closed fence and a point x,y:

【USACO 3.4】(fence4)Closed Fences - 青色有角三倍速 - 真兽亚纲—程式

Write a program which will do the following:

Test an ordered list of vertices {xi,yi}, i in (1..N) to see if the array is a valid fence.Find the set of fence sides that a person (with no height) who is standing in the plane at position (x,y) can "see" when looking at the fence. The location x,y may fall anywhere not on the fence.

A fence side can be seen if there exists a ray that connects (x,y) and any point on the side, and the ray does not intersect any other side of the fence. A side that is parallel to the line of sight is not considered visible. In the figure, above the segments x3,y3-x4,y4; x5,y5-x6,y6; and x6-y6-x1,y1 are visible or partially visible from x,y.

-------------Solution---------------

对于fence系列的吐槽详见fence9(Electric Fence)题解

本人表示计算几何实在是太E了

本题的第二问麻烦得吐血啊少年!!!!!!

Nocow上广为流传二分法有人(谁?)证明是错的

虽然二分可以AC但我还是不想写非完备程序。。。

随意写线段覆盖!!!!!!

但那个覆盖判定恶心死啦!!!!!

具体来说

设当前考察线段为ab。人站的位置为P。其他直线为cd
那么,

要么cd完全把ab挡住了(显然此时Pa与cd相交Pb与cd相交)
要么cd只遮住ab的一部分(废话、、)
对于后面一种情况

设可见部分为a0b0
则枚举所有的cd缩小a0b0

最后

若a0b0可见,则ab可见。

复杂度。。。。

 

 

 

反正过了

 

对了

 

发现一个奇葩。。。

交完题习惯看数据

发现

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

【USACO 3.4】(fence4)Closed Fences - 青色有角三倍速 - 真兽亚纲—程式
6,7,8亮了

-----------Code------------

 
  


//说明:因为最后还是不习惯用黑书上的写法所以问2还是裸写segcross,没用函数了,。。虽然感觉差不多

/*
ID:zst_0110
LANG:C++
TASK:fence4
*/
#include<stdio.h>
#include<stdlib.h>

int a[302][2];
int ans[302],top;
int n;

int intcmp(int x)
{
    return x==0?0:(x>0?1:-1);
}

int det(int x1,int y1,int x2,int y2)
{
    return x1*y2-x2*y1;
}

int cross(int da,int db,int dc)
{
    return det(a[db][0]-a[da][0],a[db][1]-a[da][1],
               a[dc][0]-a[da][0],a[dc][1]-a[da][1]);
}

int segcross(int da,int db,int dc,int dd)
{
    return (intcmp(cross(da,db,dc))*intcmp(cross(da,db,dd))<0
         && intcmp(cross(dc,dd,da))*intcmp(cross(dc,dd,db))<0);
}

bool check(int s)
{
    int a0,b0;
    int a=s,b=s+1;
    int i;
    if(!cross(0,a,b))
        return false;
    for(i=1;i<=n;i++)
        if(i!=s)
        {
            if(cross(0,a,i)*cross(0,a,i+1)<=0&&cross(i,i+1,0)*cross(i,i+1,a)<=0)
                if(cross(i,i+1,0)*cross(i,i+1,b)<=0&&cross(0,b,i)*cross(0,b,i+1)<=0)
                    return false;
        }

    if(cross(0,a,b)<0)
        a^=b^=a^=b;
    a0=a;
    b0=b;
    for(i=1;i<=n;i++)
    {
        if(cross(a,b,i)>0&&cross(0,a,i)>0&&cross(b,0,i)>0)
        {
            int cro=cross(0,i,i+1);
            if(cro>0&&cross(0,b0,i)<0)
                b0=i;
            if(cro<0&&cross(0,a0,i)>0)
                a0=i;
        }
        if(cross(a,b,i+1)>0&&cross(0,a,i+1)>0&&cross(b,0,i+1)>0)
        {
            int cro=cross(0,i+1,i);
            if(cro>0&&cross(0,b0,i+1)<0)
                b0=i+1;
            if(cro<0&&cross(0,a0,i+1)>0)
                a0=i+1;
        }
    }
    if(cross(0,a0,b0)>0)
        return true;
    return false;
}

int main()
{
    int i,j,k,m;
    freopen("fence4.in","r",stdin);
    freopen("fence4.out","w",stdout);
    
    scanf("%d",&n);
    for(i=0;i<=n;i++)
        scanf("%d%d",&a[i][0],&a[i][1]);
    a[n+1][0]=a[1][0];
    a[n+1][1]=a[1][1];
    for(i=1;i<=n;i++)
    {
        int seg1=i,seg2=i+1;
        for(j=i+1;j<=n;j++)
        {
            int jto=j+1;
            if(segcross(seg1,seg2,j,jto))
            {
                printf("NOFENCE\n");
                return 0;
            }
        }
    }
    for(i=1;i<=n;i++)
        if(check(i))
            ans[++top]=i;
    printf("%d\n",top);
    
    if(ans[top]==n&&ans[top-1]==n-1)
        ans[top]^=ans[top-1]^=ans[top]^=ans[top-1];
    
    for(i=1;i<=top;i++)
        if(ans[i]==n)
            printf("%d %d %d %d\n",a[ans[i]+1][0],a[ans[i]+1][1],a[ans[i]][0],a[ans[i]][1]);
        else
            printf("%d %d %d %d\n",a[ans[i]][0],a[ans[i]][1],a[ans[i]+1][0],a[ans[i]+1][1]);
    return 0;
}




转载于:https://www.cnblogs.com/Aoi3x/archive/2011/09/15/2645356.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值