Most Distant Point from the Sea POJ - 3525

题目链接:https://vjudge.net/problem/POJ-3525

思路:求凸包内最大圆的半径

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<math.h>
  6 #define eps 1e-8
  7 #define PI acos(-1.0)
  8 #define MAXN 110
  9 using namespace std;
 10 
 11 int n;
 12 
 13 int sgn(double x)
 14 { //符号函数
 15     if(fabs(x) < eps) return 0;
 16     if(x < 0) return -1;
 17     else return 1;
 18 }
 19 
 20 struct Point
 21 { //
 22     double x,y;
 23     Point(){}
 24     Point(double _x,double _y)
 25     {
 26         x = _x; y = _y;
 27     }
 28     Point operator -(const Point &b)const
 29     {
 30         return Point(x - b.x, y - b.y);
 31     }
 32     double operator ^(const Point &b)const
 33     { //叉积
 34         return x*b.y - y*b.x;
 35     }
 36     double operator *(const Point &b)const
 37     { //点积
 38         return x*b.x + y*b.y;
 39     }
 40 };
 41 
 42 struct Line
 43 { //向量 
 44     Point s,e; //两点
 45     double k; //斜率
 46     Line(){}
 47     Line(Point _s,Point _e)
 48     { //构造
 49         s = _s; e = _e;
 50         k = atan2(e.y - s.y,e.x - s.x);
 51     }
 52     Point operator &(const Line &b)const
 53     { //求两直线交点
 54         Point res = s;
 55         double t = ((s - b.s)^(b.s - b.e))/((s - e)^(b.s - b.e));
 56         res.x += (e.x - s.x)*t;
 57         res.y += (e.y - s.y)*t;
 58         return res;
 59     }
 60 };
 61 
 62 Line Q[MAXN];
 63 Point p[MAXN]; //记录最初给的点集
 64 Line line[MAXN]; //由最初的点集生成直线的集合
 65 Point pp[MAXN]; //记录半平面交的结果的点集
 66 
 67 //半平面交,直线的左边代表有效区域
 68 bool HPIcmp(Line a,Line b)
 69 { //直线排序函数
 70     if(fabs(a.k - b.k) > eps)return a.k < b.k; //斜率排序
 71     
 72     return ((a.s - b.s)^(b.e - b.s)) < 0;
 73 }
 74 
 75 void HPI(Line line[], int n, Point res[], int &resn)
 76 { //line是半平面交的直线的集合 n是直线的条数 res是结果
 77 //的点集 resn是点集里面点的个数
 78     int tot = n;
 79     sort(line,line+n,HPIcmp);
 80     tot = 1;
 81     for(int i = 1;i < n;i++)
 82         if(fabs(line[i].k - line[i-1].k) > eps) //去掉斜率重复的
 83             line[tot++] = line[i];
 84     int head = 0, tail = 1;
 85     Q[0] = line[0];
 86     Q[1] = line[1];
 87     resn = 0;
 88     for(int i = 2; i < tot; i++)
 89     {
 90         if(fabs((Q[tail].e-Q[tail].s)^(Q[tail-1].e-Q[tail-1].s)) < eps ||
 91            fabs((Q[head].e-Q[head].s)^(Q[head+1].e-Q[head+1].s)) < eps)
 92             return;
 93         while(head < tail && (((Q[tail]&Q[tail-1]) -
 94                                line[i].s)^(line[i].e-line[i].s)) > eps)
 95             tail--;
 96         while(head < tail && (((Q[head]&Q[head+1]) -
 97                                line[i].s)^(line[i].e-line[i].s)) > eps)
 98             head++;
 99         Q[++tail] = line[i];
100     }
101     while(head < tail && (((Q[tail]&Q[tail-1]) -
102                            Q[head].s)^(Q[head].e-Q[head].s)) > eps)
103         tail--;
104     while(head < tail && (((Q[head]&Q[head-1]) -
105                            Q[tail].s)^(Q[tail].e-Q[tail].e)) > eps)
106         head++;
107     if(tail <= head + 1) return;
108     for(int i = head; i < tail; i++)
109         res[resn++] = Q[i]&Q[i+1];
110     if(head < tail - 1)
111         res[resn++] = Q[head]&Q[tail];
112 }
113 
114 double dist(Point a,Point b)
115 { //两点间距离
116     return sqrt((a-b)*(a-b));
117 }
118 
119 void change(Point a,Point b,Point &c,Point &d,double p)
120 { //将线段ab往左移动距离p,修改得到线段cd
121     double len=dist(a,b);
122     /*三角形相似推出下面公式*/
123     double dx=(a.y-b.y)*p/len;
124     double dy=(b.x-a.x)*p/len;
125     c.x=a.x+dx; c.y=a.y+dy;
126     d.x=b.x+dx; d.y=b.y+dy;
127 }
128 
129 double BSearch()
130 { //二分搜索 
131     double l=0,r=100000;
132     double ans=0;
133     while(r-l>=eps)
134     {
135         double mid=(l+r)/2;
136         for(int i=0;i < n;i++)
137         {
138             Point t1,t2;
139             change(p[i],p[(i+1)%n],t1,t2,mid);
140             line[i]=Line(t1,t2);
141         }
142         int resn;
143         HPI(line,n,pp,resn);
144         //等于0说明移多了
145         if(resn==0) r=mid-eps;
146         else l=mid+eps;
147     }
148     return l;
149 }
150 
151 int main()
152 {
153     while(~scanf("%d",&n)&&n)
154     {
155         for(int i = 0;i < n;i++)
156             scanf("%lf%lf",&p[i].x,&p[i].y);
157         printf("%.6f\n",BSearch());
158     }
159     return 0;
160 }
 

猜你喜欢

转载自www.cnblogs.com/Vampire6/p/12464514.html
今日推荐