poj 3525 Most Distant Point from the Sea - 求到海岸最远的点 - 半平面交

/*
poj 3525 Most Distant Point from the Sea - 求到海岸最远的点 - 半平面交


就是求多边形最大的内接圆的半径

枚举半径
将所有海岸沿法向量向里推进半径的距离,求按平面的交,若多边形还有核,则这个半径存在
*/
#include<stdio.h>  
#include<math.h>  
#include <algorithm>    
using namespace std;    
  
const double eps=1e-9;  
struct point   
{  
    double x,y;  
	point(){}
	point(double a,double b):x(a),y(b){}
}dian[803];  
point jiao[803];  
struct line    
{    
    point s,e;    
    double angle;    
}xian[803];    
int n,yong;  
bool mo_ee(double x,double y)    
{    
    double ret=x-y;    
    if(ret<0) ret=-ret;    
    if(ret<eps) return 1;    
    return 0;    
}    
bool mo_gg(double x,double y)  {   return x > y + eps;} // x > y       
bool mo_ll(double x,double y)  {   return x < y - eps;} // x < y       
bool mo_ge(double x,double y) {   return x > y - eps;} // x >= y       
bool mo_le(double x,double y) {   return x < y + eps;}     // x <= y       
point mo_intersection(point u1,point u2,point v1,point v2)    
{    
    point ret=u1;    
    double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))    
        /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));    
    ret.x+=(u2.x-u1.x)*t;    
    ret.y+=(u2.y-u1.y)*t;    
    return ret;    
}    
double mo_xmult(point p2,point p0,point p1)//p1在p2左返回负,在右边返回正    
{    
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);    
}    
  
  
void mo_HPI_addl(point a,point b)    
{    
    xian[yong].s=a;    
    xian[yong].e=b;    
    xian[yong].angle=atan2(b.y-a.y,b.x-a.x);    
    yong++;    
}    
//半平面交  
bool mo_HPI_cmp(const line& a,const line& b)  
{  
    if(mo_ee(a.angle,b.angle))  
    {  
        return mo_gg( mo_xmult(b.e,a.s,b.s),0);  
    }else  
    {  
        return mo_ll(a.angle,b.angle);  
    }  
}  
int mo_HPI_dq[803];  
bool mo_HPI_isout(line cur,line top,line top_1)  
{  
    point jiao=mo_intersection(top.s,top.e,top_1.s,top_1.e);  
    return mo_ll( mo_xmult(cur.e,jiao,cur.s),0);//若顺时针时应为mo_gg  
}  
int mo_HalfPlaneIntersect(line *xian,int n,point *jiao)  
{  
    int i,j,ret=0;  
    sort(xian,xian+n,mo_HPI_cmp);  
    for (i = 0, j = 0; i < n; i++)  
    {  
        if (mo_gg(xian[i].angle,xian[j].angle))  
        {  
            xian[++j] = xian[i];  
        }  
    }  
    n=j+1;  
    mo_HPI_dq[0]=0;  
    mo_HPI_dq[1]=1;  
    int top=1,bot=0;  
    for (i = 2; i < n; i++)  
    {  
        while (top > bot && mo_HPI_isout(xian[i], xian[mo_HPI_dq[top]], xian[mo_HPI_dq[top-1]])) top--;  
        while (top > bot && mo_HPI_isout(xian[i], xian[mo_HPI_dq[bot]], xian[mo_HPI_dq[bot+1]])) bot++;  
        mo_HPI_dq[++top] = i; //当前半平面入栈  
    }  
    while (top > bot && mo_HPI_isout(xian[mo_HPI_dq[bot]], xian[mo_HPI_dq[top]], xian[mo_HPI_dq[top-1]])) top--;  
    while (top > bot && mo_HPI_isout(xian[mo_HPI_dq[top]], xian[mo_HPI_dq[bot]], xian[mo_HPI_dq[bot+1]])) bot++;  
    mo_HPI_dq[++top] = mo_HPI_dq[bot];  
    for (ret = 0, i = bot; i < top; i++, ret++)  
    {  
        jiao[ret]=mo_intersection(xian[mo_HPI_dq[i+1]].s,xian[mo_HPI_dq[i+1]].e,xian[mo_HPI_dq[i]].s,xian[mo_HPI_dq[i]].e);  
    }  
    return ret;  
}  
//求法向量
point mo_getfaxian(point xiang)
{
     	point a;
     	if(mo_ee(xiang.x,0))
     	{
               	a.x=1;
               	a.y=0;
               	return a;
     	}else if(mo_ee(xiang.y,0))
     	{
               	a.x=0;
               	a.y=1;
               	return a;
     	}else
     	{
               	a.x=1;
               	a.y=-1.0*xiang.x/xiang.y;
               	return a;
     	}
 
}
//线se推进一段距离
line mo_line_tui(point s,point e,double tui)
{
	line ret;
	point fa=mo_getfaxian(point(e.x-s.x,e.y-s.y));
	if(mo_ll(mo_xmult(e,point(s.x+fa.x,s.y+fa.y),s),0))
	{
		fa.x=-fa.x;
		fa.y=-fa.y;
	}
	double len=sqrt(fa.x*fa.x+fa.y*fa.y);
	len=len/tui;
	fa.x=fa.x/len;
	fa.y=fa.y/len;

	s.x=s.x+fa.x,s.y=s.y+fa.y;
	e.x=e.x+fa.x,e.y=e.y+fa.y;

	ret.s=s;
	ret.e=e;
	return ret;
}
int kexing(double jia)
{
	int i;
	yong=0;
	line temp;
	for(i=0;i<n;++i)
	{
		temp=mo_line_tui(dian[i],dian[(i+1)%n],jia);
		mo_HPI_addl(temp.s,temp.e);
	}
	int ret=mo_HalfPlaneIntersect(xian,n,jiao);
	if(ret<3)
	{
		return 0;
	}
	return 1;
}
int main()
{
	int i;
	double banjing;
	while(scanf("%d",&n),n)
	{
		yong=0;
		for(i=0;i<n;++i)
		{
			scanf("%lf%lf",&dian[i].x,&dian[i].y);
		}
		double shang=5001,xia=0,mid;
		while(xia+1e-6<shang)
		{
			mid=(shang+xia)/2;
			int ret=kexing(mid);
			if(ret)
			{
				banjing=mid;
				xia=mid+1e-6;
			}else
			{
				shang=mid-1e-6;
			}
		}
		printf("%lf\n",banjing);
	}
	return 0;
}

你可能感兴趣的:(poj 3525 Most Distant Point from the Sea - 求到海岸最远的点 - 半平面交)