码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-10-01 16:29:54      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:problem   init   ret   opera   play   class   def   inter   name   

题目链接: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】计算凸多边形最大内切圆(模板 半平面交向量平移)

标签:problem   init   ret   opera   play   class   def   inter   name   

原文地址:https://www.cnblogs.com/xiaobuxie/p/11615367.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!