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
以上是关于poj3525计算凸多边形最大内切圆(模板 半平面交向量平移)的主要内容,如果未能解决你的问题,请参考以下文章
poj 3525Most Distant Point from the Sea二分+半平面交
POJ3525:Most Distant Point from the Sea(二分+半平面交)
例4.10 POJ3525/LA3890离海最远的点 半平面交 + 二分法 + double小数点后有效位数处理方式/printf与g++c++的问题