您的位置:首页 > 其它

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

2013-08-10 20:33 609 查看
/*
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: