您的位置:首页 > 其它

POJ 3525 Most Distant Point from the Sea(半平面交)

2012-12-27 10:55 453 查看
题目链接:http://poj.org/problem?id=3525

题意:多边形内一个圆。该圆的最大半径是多少?

思路:二分半径r。将每条边向内移动r的距离。若得到的还是多边形则说明r可以。

int DB(double x)
{
if(x>1e-10) return 1;
if(x<-1e-10) return -1;
return 0;
}

struct point
{
double x,y;

point(){}
point(double _x,double _y)
{
x=_x;
y=_y;
}

void read()
{
RD(x,y);
}

void output()
{
printf("(%.2lf %.2lf)",x,y);
}

point operator+(point a)
{
return point(x+a.x,y+a.y);
}
point operator-(point a)
{
return point(x-a.x,y-a.y);
}

double operator*(point a)
{
return x*a.y-y*a.x;
}

point operator*(double t)
{
return point(x*t,y*t);
}

point operator/(double t)
{
return point(x/t,y/t);
}

bool operator==(point a)
{
return DB(x-a.x)==0&&DB(y-a.y)==0;
}

bool operator!=(point a)
{
return DB(x-a.x)||DB(y-a.y);
}
};

point a
,b
;
int n;

//t在ab的左侧返回正值
double cross(point a,point b,point t)
{
return point(b-a)*point(t-a);
}

point getCross(point a,point b,point p,point q)
{
double s1=(a-p)*(b-p);
double s2=(b-q)*(a-q);
double t=s1+s2;
return (p*s2+q*s1)/(s1+s2);
}

double getDist(point a,point b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}

void moveSegment(point &p1,point &p2,double r)
{
r/=getDist(p1,p2);
point p=point(p1.y-p2.y,p2.x-p1.x)*r;
p1=p1+p;
p2=p2+p;
}

void cut(point a[],int &n,point p1,point p2)
{
point b
,p;
int i,m=n,t1,t2;
FOR0(i,n) b[i]=a[i];
b
=b[0];
n=0;
FOR0(i,m)
{
t1=DB(cross(p1,p2,b[i]));
t2=DB(cross(p1,p2,b[i+1]));
if(!t1||!t2)
{
if(!t1) a[n++]=b[i];
if(!t2) a[n++]=b[i+1];
}
else if(t1>0&&t2>0) a[n++]=b[i],a[n++]=b[i+1];
else if(t1*t2==-1)
{
p=getCross(p1,p2,b[i],b[i+1]);
if(t1>0) a[n++]=b[i],a[n++]=p;
else a[n++]=p,a[n++]=b[i+1];
}
}
if(!n) return;
m=1;
FOR1(i,n-1) if(a[i]!=a[i-1]) a[m++]=a[i];
if(a[m-1]==a[0]) m--;
n=m;
}

double getRadius(point a[],int n)
{
double low=0,high=1e10,mid;
point p1,p2,b
;
int i,m;

a
=a[0];
while(high-low>1e-10)
{
mid=(low+high)/2;
m=n;
FOR0(i,n) b[i]=a[i];
FOR0(i,n)
{
p1=a[i];p2=a[i+1];
moveSegment(p1,p2,mid);
cut(b,m,p1,p2);
}
if(m>0) low=mid+1e-10;
else high=mid-1e-10;
}
return mid;
}

int main()
{
while(scanf("%d",&n),n)
{
int i;
FOR0(i,n) a[i].read();
double r=getRadius(a,n);
printf("%.6lf\n",r);
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: