这道题的意思就是给你一个凸包,然后再给一个在凸包外的点,求站在这个点,能看到的凸包的周长,题意很简单,做法也很明白。。就是实现起来有点坑。。。。
需要考虑的就是凸包上与给出的点共线的点,这个情况一定要考虑,最开始我是用的atan2对凸包进行分情况极角排序。。但是好像是有精度问题什么的。
写了一天写了5000+b都A不了。。太坑了,
后来换了一种极角排序方法,就是用象限极角排序,如下图,然后根据凸包横跨象限的情况来讨论,因为给出的点是逆时针的,所以比较好处理。
代码贴上~~~~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define inf 0x7ffffff
using namespace std;
const double eps = 1e-10;
bool dy(double x,double y) { return x > y + eps;} // x > y
bool xy(double x,double y) { return x < y - eps;} // x < y
bool dyd(double x,double y) { return x > y - eps;} // x >= y
bool xyd(double x,double y) { return x < y + eps;} // x <= y
bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y
struct P
{
double x,y;
int index;
};
P r;
int quat(P a)
{
if(dy(a.x,0.0) && dyd(a.y,0.0)) return 1;
if(xyd(a.x,0.0) && dy(a.y,0.0))return 2;
if(xy(a.x,0.0)&& xyd(a.y,0.0)) return 3;
if(dyd(a.x,0.0)&& xy(a.y,0.0)) return 4;
}
double det(P r,P a,P b)
{
return (a.x-r.x)*(b.y-r.y)-(b.x-r.x)*(a.y-r.y);
}
bool cmp(P a,P b)
{
P p1,p2;
p1.x=a.x-r.x;
p1.y=a.y-r.y;
p2.x=b.x-r.x;
p2.y=b.y-r.y;
int l1=quat(p1),l2=quat(p2);
if(l1==l2)
{
double c=det(r,b,a);
if(dd(c,0.0)) //同一象限共线的点,按照与r的距离从小到大排序
{
if(dd(fabs(p1.x),fabs(p2.x)))
return xy(fabs(p1.y),fabs(p2.y));
return xy(fabs(p1.x),fabs(p2.x));
}
return xy(c,0.0);
}
return l1<l2;
}
double dis(P a,P b)
{
double c=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
return sqrt(c);
}
int mn,mk;
double sum;
P qs[1000000],ps[1000000];
int n;
int vis[10];
void solve()
{
int i=mn;
while(1)
{
sum+=dis(ps[(i%n+n)%n],ps[((i+1)%n+n)%n]);
if(((i+1)%n+n)%n==mk)
break;
i++;
}
}
int main()
{
while(~scanf("%d",&n))
{
sum=0.0;
int i;
memset(vis,0,sizeof(vis));
for( i=0;i<n;i++)
{
scanf("%lf%lf",&qs[i].x,&qs[i].y);
qs[i].index=i;
ps[i]=qs[i];
}
scanf("%lf%lf",&r.x,&r.y);
sort(qs,qs+n,cmp);
int l=0;
for( i=0;i<n;i++)
{
P a;
a.x=qs[i].x-r.x;
a.y=qs[i].y-r.y;
vis[quat(a)]=1;
}
for( i=1;i<=4;i++)
l+=vis[i];
if(l==1)
{
mk=qs[0].index;
mn=qs[n-1].index;
}
else
{
if(vis[1]==vis[4] && vis[1]==1 && l==2) //只横跨1 4象限特殊考虑
{
for( i=0;i<n;i++)
{
P a;
a.x=qs[i].x-r.x;
a.y=qs[i].y-r.y;
if(quat(a)==1)
mn=qs[i].index;
}
for( i=0;i<n;i++)
{
P a;
a.x=qs[i].x-r.x;
a.y=qs[i].y-r.y;
if(quat(a)==4)
{
mk=qs[i].index;
break;
}
}
}
else
{
mk=qs[0].index;
int a=n-1;
mn=qs[a].index;
while(dd(det(r,qs[a],qs[a-1]),0.0))
{
mn=qs[a-1].index;
a--;
}
}
}
solve();
printf("%.3lf\n",sum);
}
return 0;
}