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:
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可见。
复杂度。。。。
反正过了
对了
发现一个奇葩。。。
交完题习惯看数据
发现
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;
}