链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=533&page=show_problem&problem=4142

提议:海中一个凸多边形小岛,求出岛上离海最远点到海的距离。

思路:就是求这个凸多边形内切圆的最大半径。对半径进行二分,将多边形所有边向内平移半径的长度,然后求半平面交,如果有交则有满足的点。

 在poj上用g++交wa了,c++又过了。。。坑

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200;
const double eps=1e-8;
struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y) {}
};
typedef Point Vector;
struct DLine
{
    Point P;
    Vector v;
    double ang;
    DLine() {}
    DLine(Point P,Vector v):P(P),v(v)
    {
        ang=atan2(v.y,v.x);
    }
    bool operator < (const DLine& L) const
    {
        return ang<L.ang;
    }
};
Vector operator + (Vector A,Vector B)
{
    return Vector(A.x+B.x,A.y+B.y);
}
Vector operator - (Vector A,Vector B)
{
    return Vector(A.x-B.x,A.y-B.y);
}
Vector operator * (Vector A,double p)
{
    return Vector(A.x*p,A.y*p);
}
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
bool operator == (const Point& a,const Point& b)
{
    return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
}
double Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}
double Length(Vector A)
{
    return sqrt(Dot(A,A));
}
double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}
Vector Normal(Vector A)//向量的单位法线,即左转90度
{
    double L=Length(A);
    return Vector(-A.y/L,A.x/L);
}
bool OnLeft(DLine L,Point p)
{
    return Cross(L.v,p-L.P)>0;
}
Point GetIntersection(DLine a,DLine b)
{
    Vector u=a.P-b.P;
    double t=Cross(b.v,u)/Cross(a.v,b.v);
    return a.P+a.v*t;
}
int HalfPlaneIntersection(DLine* L,int n){
    sort(L,L+n);
    int first,last;
    Point *p=new Point[n];
    DLine *q=new DLine[n];
    q[first=last=0]=L[0];
    for(int i=1; i<n; i++)
    {
        while(first<last && !OnLeft(L[i],p[last-1])) last--;
        while(first<last && !OnLeft(L[i],p[first])) first++;
        q[++last]=L[i];
        if(fabs(Cross(q[last].v,q[last-1].v))<eps)
        {
            last--;
            if(OnLeft(q[last],L[i].P)) q[last]=L[i];
        }
        if(first<last) p[last-1]=GetIntersection(q[last-1],q[last]);
    }
    while(first<last && !OnLeft(q[first],p[last-1])) last--;
    if(last-first <= 1) return 0;
    p[last]=GetIntersection(q[last],q[first]);
    return (last-first+1);
}
int n;
Point p[maxn];
DLine l[maxn];
Vector v[maxn],v2[maxn];
void solve()
{
    double left=0,right=10000;//二分
    while(right-left>1e-6)
    {
        double mid=left+(right-left)/2;
        for(int i=0; i<n; i++)
            l[i]=DLine(p[i]+v2[i]*mid,v[i]);
        int m=HalfPlaneIntersection(l,n);
        if(!m) right=mid;
        else left=mid;
    }
    printf("%.6lf\n",left);
}

int main()
{
   // freopen("in.cpp","r",stdin);
    while(scanf("%d",&n) && n)
    {
        for(int i=0; i<n; i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        for(int i=0; i<n; i++)
        {
            v[i]=p[(i+1)%n]-p[i];
            v2[i]=Normal(v[i]);
        }
        solve();
    }
    return 0;
}

 

 posted on 2013-08-05 19:23  ∑求和  阅读(160)  评论(0编辑  收藏  举报