您的位置:首页 > 其它

POJ 3525 Most Distant Point from the Sea

2017-09-20 18:35 375 查看

题意 :给你一个小岛,是一个凸多边形,问你这个多边形的内部的点到所有边的最小值最大。

题解 :对于最小值最大的问题,不难想到要用二分去做,不难发现这个题的距离是满足二分性质的,然后将每天边向内部缩 dist 怎么缩呢 ? (通过一天边旋转90 度 就可以了) 。由于这个题给你的是一个凸多边形所以剩下的就可以用半平面交解决了,如果半平面交存在,那么这个答案检验就是可以的。

emmm……. 剩下的就是半平面交的模版了。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define PI 3.1415926
using namespace std;
#define N 1005
const double eps=1e-8;
int dcmp(double x) {
if (x<=eps&&x>=-eps) return 0;
return (x>0)?1:-1;
}
struct Vector {
double x,y;
Vector(double X=0,double Y=0){
x=X,y=Y;
}
};
typedef Vector Point;

struct Line {
Point p;
Vector v;
double ang;
Line(Point P=Point(0,0),Vector V=Vector(0,0)) {
p=P,v=V;
ang=atan2(v.y,v.x);
}
bool operator < (const Line &a) const {
return ang<a.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 b) {return Vector(a.x*b,a.y*b);}

int n,l,r,cnt;
double ans;
Line L
,q
;
Point p
,poly
;
double Cross(Vector a,Vector b) {
return a.x*b.y-a.y*b.x;
}
Point GLI(Point P,Vector v,Point Q,Vector w) {
Vector u=P-Q;
double t=Cross(w,u)/Cross(v,w);
return P+v*t;
}
bool Onleft(Line m,Point P) {
Vector w=P-m.p;
return dcmp(Cross(m.v,w))>=0;
}
void halfp(){
sort(L+1,L+n+1);
cnt=0;
q[l=r=1]=L[1];
for (int i=2;i<=n;++i) {
while (l<r&&!Onleft(L[i],p[r-1])) --r;
while (l<r&&!Onleft(L[i],p[l])) ++l;
q[++r]=L[i];
if (dcmp(Cross(q[r].v,q[r-1].v))==0) {
--r;
if (Onleft(q[r],L[i].p))
q[r]=L[i];
}
if (l<r)
p[r-1]=GLI(q[r-1].p,q[r-1].v,q[r].p,q[r].v);
}
while (l<r&&!Onleft(q[l],p[r-1]))
--r;
if (r-l<=1) return;
p[r]=GLI(q[r].p,q[r].v,q[l].p,q[l].v);
for (int i=l;i<=r;++i) poly[++cnt]=p[i];
}
double Area() {
double ans=0;
for (int i=2;i<cnt;++i)
ans+=Cross(poly[i]-poly[1],poly[i+1]-poly[1]);
return fabs(ans/2);
}

int main() {
while(scanf("%d",&n) && n) { // 输入点的个数
Point temp
,temp0,temp1;
Point pp
;
Line LL
;
double ang
;
for (int i=1;i<=n;++i) {
double x,y;
scanf ("%lf%lf",&x,&y);
pp[i] = Point (x,y);
temp[i] = pp[i];
} // 开始需要设置一个无限大的区域
pp[n + 1] = pp[1];
temp[n + 1] = pp[1];
for (int i = 1;i <= n; ++ i) {
L[i] = Line(pp[i]
4000
,pp[i + 1] - pp[i]);
LL[i] = L[i];
ang[i] = L[i].ang;
}
//    for (int i = 1;i <= n; ++ i) printf("%d  %.6f\n",i,LL[i].ang);
L[++n] = Line(Point(0,10000),Vector(0,-10000));
L[++n] = Line(Point(0,0),Vector(10000,0));
L[++n] = Line(Point(10000,0),Vector(0,10000));
L[++n] = Line(Point(10000,10000),Vector(-10000,0));
double R = 10000.0,Ll = 0.0;
double mid = (R + Ll) / 2;
//    halfp();
//    printf("%.6f\n",Area());
//    cout << cnt << endl;
//    for (int i = 1;i <= n - 4; ++ i) printf("%d  %.6f\n",i,LL[i].ang);
while (R - Ll > eps) {
mid = (R + Ll) / 2.0;;
for (int i = 1;i <= n - 4; ++ i) {
double angd = ang[i] + PI / 2.0;
double addx = mid * cos (angd);
double addy = mid * sin (angd);
temp0 = temp[i];
temp1 = temp[i + 1];
temp0.x += addx,temp0.y += addy;
temp1.x += addx,temp1.y += addy;
L[i] = Line (temp0,temp1 - temp0);
//   printf("%.3f %.3f %.3f\n",mid,L[i].p.x,L[i].p.y);
}
L
= Line(Point(0,10000),Vector(0,-10000));
L[n - 1] = Line(Point(0,0),Vector(10000,0));
L[n - 2] = Line(Point(10000,0),Vector(0,10000));
L[n - 3] = Line(Point(10000,10000),Vector(-10000,0));
halfp();
if (cnt >= 1) Ll = mid;
else R = mid;
//        printf ("%.6f\n",mid);
}
printf ("%.6f\n",mid);
}
return 0;
}
/*
3
0.000 312.500
9901.179 -296.464
7044.194 690.641
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 计算几何