poj3525计算凸多边形最大内切圆(模板 半平面交向量平移)

Posted xiaobuxie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj3525计算凸多边形最大内切圆(模板 半平面交向量平移)相关的知识,希望对你有一定的参考价值。

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

二分最大内切圆的半径,然后把求多边形内核的那几个向量向内平移半径。若是构成内核,则半径符合,反之不符合。

如何判断是否构成内核?由于内核是若干个向量围起来的,所以只要向量大于等于3即可

技术图片
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 using namespace std;
  6 #define eps 1e-8
  7 const int N = 107;
  8 const double pi = acos(-1.0);
  9 int n;
 10 struct Point
 11     double x,y;
 12     Point operator - (const Point& b)const
 13         return (Point)x-b.x,y-b.y;
 14     
 15     double operator ^ (const Point& b)const
 16         return x*b.y - b.x*y;
 17     
 18     Point operator * (const double b)
 19         return (Point)x*b,y*b;
 20     
 21     Point operator + (const Point& b)const
 22         return (Point)x+b.x,y+b.y;
 23     
 24 p[N],quep[N];
 25 struct Line
 26     Point s,t;
 27     double ang;
 28     bool operator < (const Line& o)const
 29         if(o.ang != ang) return ang < o.ang;
 30         return ( (o.t-s)^(o.s - s) ) > 0;
 31     
 32 L[N],teml[N],quel[N];
 33 int sgn(double x)
 34     if(fabs(x) < eps) return 0;
 35     if(x < 0 ) return -1;
 36     return 1;
 37 
 38 Point cal(Point p,double ag,double d)
 39     Point ans;
 40     ans.x = p.x + d*sin(ag);
 41     ans.y = p.y - d*cos(ag);
 42     return ans;
 43 
 44 void init(double d)
 45     for(int i = 1;i <= n ;++i)
 46         L[i].ang = teml[i].ang;
 47         L[i].s = cal(teml[i].s,L[i].ang,d);
 48         L[i].t = cal(teml[i].t,L[i].ang,d);
 49     
 50 
 51 bool onleft(Point u,Line a)
 52     return sgn( (a.s - u)^(a.t - u) ) > 0;
 53 
 54 Point line_inter(Line l1,Line l2)
 55     double b = ((l1.t-l1.s)^(l2.s-l1.s))/((l2.t-l2.s)^(l1.t-l1.s));
 56     return l2.s + (l2.t - l2.s)*b;
 57 
 58 bool judge(double d)
 59 //    cerr<<L[1].s.x<<‘ ‘<<L[1].s.y<<‘ ‘<<L[1].t.x<<‘ ‘<<L[1].t.y<<‘ ‘<<L[1].ang/pi*180<<endl;
 60 //    cerr<<2.5*sin(L[1].ang)<<‘ ‘<<2.5*cos(L[1].ang)<<endl;
 61 //    cerr<<d<<endl;
 62     init(d);
 63     int h,t;
 64     h = t = 1;
 65     quel[1] = L[1];
 66     for(int i =2; i<=n;++i)
 67 //        cerr<<‘a‘<<teml[i].s.x<<‘ ‘<<teml[i].s.y<<‘ ‘<<teml[i].t.x<<‘ ‘<<teml[i].t.y<<‘ ‘<<d<<endl;
 68 //        cerr<<L[i].s.x<<‘ ‘<<L[i].s.y<<‘ ‘<<L[i].t.x<<‘ ‘<<L[i].t.y<<‘ ‘<<d<<endl;
 69         while ( h<t && onleft(quep[t-1],L[i])) --t;
 70         while ( h<t && onleft(quep[h],L[i])) ++h;
 71         quel[++t] = L[i];
 72         if( h<t ) quep[t-1] = line_inter(quel[t-1],quel[t]);
 73     
 74     while( h<t && onleft(quep[t-1],quel[h])) --t;
 75     quep[t] = line_inter(quel[h],quel[t]);
 76 //    cerr<<t<<‘ ‘<<h<<endl;
 77     return t-h > 1;
 78 
 79 int main()
 80     while(~scanf("%d",&n) && n)
 81         for(int i = 1;i<=n;++i) scanf("%lf %lf",&p[i].x,&p[i].y);
 82         reverse(p+1,p+1+n);
 83         p[n+1] = p[1];
 84         for(int i = 1;i <= n ;++i) teml[i]=(Line)p[i],p[i+1],atan2(p[i+1].y-p[i].y,p[i+1].x-p[i].x);
 85         sort(teml+1,teml+1+n);
 86         int nn = 1;
 87         for(int i = 2;i <= n; ++i)
 88             if(teml[i].ang != teml[i-1].ang) teml[++nn] = teml[i];
 89         
 90         n = nn;
 91         double l = 0,r = 10000000,res;
 92         while((r-l) >= eps)
 93             double mid = (l+r)/2;
 94             if(judge(mid))
 95                 res = mid;
 96                 l = mid;
 97             
 98             else r = mid;
 99         
100         printf("%.6f\n",res);
101     
102     return 0;
103 
View Code

 

以上是关于poj3525计算凸多边形最大内切圆(模板 半平面交向量平移)的主要内容,如果未能解决你的问题,请参考以下文章

poj 3525Most Distant Point from the Sea二分+半平面交

poj 3525 凸多边形多大内切圆

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

POJ 3525 /// 半平面交 模板

例4.10 POJ3525/LA3890离海最远的点 半平面交 + 二分法 + double小数点后有效位数处理方式/printf与g++c++的问题

POJ 3525 Most Distant Point from the Sea (半平面交)