码迷,mamicode.com
首页 > 其他好文 > 详细

POJ3525:Most Distant Point from the Sea(二分+半平面交)

时间:2019-04-09 11:10:08      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:1.0   sort   凸多边形   左移   printf   bool   class   plane   a+b   

pro:给定凸多边形,求凸多边形内的点到最近边界的最远距离。

sol:显然是二分一个圆,使得圆和凸多边形不相交,但是这样很难实现。 由于是凸多边形,我们可以把二分圆转化为二分凸多边形的移动。 如果每一边向左移动Mid后,任然存在“核”,则表示存在一点合法。

直线移动:移动起点即可,方向不变。  

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=10010;
const double eps=1e-12;
struct point{
    double x,y;
    point(){}
    point(double xx,double yy):x(xx),y(yy){}
};
struct line{
    point a;//起点
    point p;//起点到终点的向量
    double angle;
};
double dot(point a,point b){ return a.x*b.x+a.y*b.y;}
double det(point a,point b){ return a.x*b.y-a.y*b.x;}
point operator *(point A,double p){ return point(A.x*p,A.y*p);}
point operator +(point A,point B){return point(A.x+B.x,A.y+B.y);}
point operator -(point A,point B){return point(A.x-B.x,A.y-B.y);}
double getangle(point a){ return atan2(a.y,a.x);}
double getangle(line a){ return getangle(a.p);}
point llintersect(line A,line B)
{
    point C=A.a-B.a;
    double t=det(C,B.p)/det(B.p,A.p);
    return A.a+A.p*t;
}
point s[maxn]; line t[maxn],q[maxn]; int head,tail;
bool cmp(line a,line b){
    double A=getangle(a),B=getangle(b);
    point t=(b.a+b.p)-a.a;
    if(fabs(A-B)<eps) return det(a.p,t)>=0.0;
    return A<B;
}
bool onright(line P,line a,line b)
{
    point o=llintersect(a,b);
    point Q=o-P.a;
    return det(Q,P.p)>0; //如果同一直线上不能相互看到,则>=0
}
void Change(int i,double Mid) //(-y,x)
{
    point p=point(-1.0*t[i].p.y,t[i].p.x);
    t[i].a=t[i].a+p*(Mid/sqrt(dot(t[i].p,t[i].p)));
}
bool halfplaneintersect(int N,double Mid)
{
    s[N+1]=s[1];
    rep(i,1,N) t[i].a=s[i],t[i].p=s[i+1]-s[i];
    rep(i,1,N) Change(i,Mid);
    sort(t+1,t+N+1,cmp);
    int tot=0;
    rep(i,1,N-1) {
        if(fabs(getangle(t[i])-getangle(t[i+1]))>eps)
          t[++tot]=t[i];
    }
    t[++tot]=t[N]; head=tail=0;
    rep(i,1,tot){
        while(tail>head+1&&onright(t[i],q[tail],q[tail-1])) tail--;
        while(tail>head+1&&onright(t[i],q[head+1],q[head+2])) head++;
        q[++tail]=t[i];
    }
    while(tail>head+1&&onright(t[head+1],q[tail],q[tail-1])) tail--;return tail-head>2;
}
void solve(int N)
{
    for(int i=1;i<=N;i++) scanf("%lf%lf",&s[i].x,&s[i].y);
    double L=0,R=200010,Mid,ans; int T=50;
    while(T--){
        Mid=(L+R)/2;
        if(halfplaneintersect(N,Mid)) ans=Mid,L=Mid;
        else R=Mid;
    }
    printf("%.10lf\n",ans);
}
int main()
{
    int N;
    while(~scanf("%d",&N)&&N) solve(N);
    return 0;
}

 

POJ3525:Most Distant Point from the Sea(二分+半平面交)

标签:1.0   sort   凸多边形   左移   printf   bool   class   plane   a+b   

原文地址:https://www.cnblogs.com/hua-dong/p/10675484.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!