【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 }

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

时间: 2024-08-05 11:01:23

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

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

0) 题意: 题意很简单,给出一张四面环海的岛屿的地图,岛屿用顶点表示(题目数据保证岛屿是凸多边形--所谓凸多边形与凹多边形区别,凸多边形就是把一个多边形任意一边向两方无限延长成为一条直线,如果多边形的其他各边均在此直线的同旁,那么这个多边形就叫做凸多边形.)找出岛屿上距离大海距离最长的一个点.即求岛屿上距离岛屿各条边边中最短的距离是所有点中最长的那个点.即求岛屿中的内接圆的圆心点.输出这个点到岛屿的边的最短的距离.即该岛屿中那个内接圆的半径... 分析: 半平面交求内核点集是一个点的情况(用精

「专题总结」半平面交(6/8completed)

还是题都没做完就来写一部分题解了,因为最近很忙(其实是效率太低),所以可能一时半会回不来这个专题. 为了防止什么都没剩下忘干净,于是乎瞎写个题解记录一下... 还是一如既往的不擅长集合. 刚开始我看到半平面交我还以为是用来解决三维计算几何问题的,吓一跳. 半平面不用多说,就是一条直线把一个二维平面分成两半,其中的一半. 半平面交其实很好理解,就是同一个二维平面中若干个半平面相交的部分. 维护的方法其实挺草率的,和凸包有不少互通的地方,只不过因为封闭所以是双端队列. 凸包偏向于点,半平面交偏向于线

Rotating Scoreboard(半平面交模板题)

Rotating Scoreboard http://poj.org/problem?id=3335 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8506   Accepted: 3357 Description This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spe

半平面交 模板 poj 3335 poj 3130 poj 1474 判断半平面交是否为空集

半平面交模板 const double pi= acos(-1.0); #define arc(x) (x / 180 * pi) const double EPS = 1e-8; const int Max_N = 105; struct Point{ double x,y; Point(){} Point(double x, double y):x(x),y(y){} Point operator - (Point p){ return Point(x- p.x , y - p.y ) ;

poj 3384 Feng Shui 半平面交的应用 求最多覆盖凸多边形的面积的两个圆 的圆心坐标

题目来源: http://poj.org/problem?id=3384 分析: 用半平面交将多边形的每条边一起向"内"推进R,得到新的多边形(半平面交),然后求多边形的最远两点. 代码如下: const double EPS = 1e-10; const int Max_N = 105 ; struct Point{ double x,y; Point(){} Point(double x, double y):x(x),y(y){} Point operator - (Point

【BZOJ2618】【Cqoi2006】凸多边形 半平面交 、算法的深度细节剖析。

题解:虽然这道题数据范围太小,O(n*n)的算法都能过,但是我为了练手仍写了半平面交.. 半平面交: 我们规定:一个基准点+一个向量(本质是有向直线,)就算一个半平面,现在要求出半平面交,然后做一些事情.. 那么可以过每个半平面的基准点做一条平行于x轴的向右的射线,此射线与向量代表直线的夹角为其"极角".. 我们可以把所有半平面(Line,或者说叫有向直线)以其极角为键值排序, 然后扫一圈,围出来一个图形,即要求的半平面交.. 实现过程不妨看代码,有详细注释. 代码中有几个需要画图的地

半平面交总结and模板

博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/40859973 这两天刷了POJ上几道半平面交,对半平面交有了初步的体会,感觉半平面交还是个挺实用的知识点. 半平面交主要是看的ZZY的国家队论文,他提出的是一种O(n×log(n))的排序增量法. 附论文地址: 算法合集之<半平面交的新算法及其实用价值>. POJ 3335 Rotating Scoreboard 题目大意: World finals 要开始了,比赛场地是一

半平面交模板

摘自http://blog.csdn.net/accry/article/details/6070621 首先解决问题:什么是半平面? 顾名思义,半平面就是指平面的一半,我们知道,一条直线可以将平面分为两个部分,那么这两个部分就叫做两个半平面. 然后,半平面怎么表示呢? 二维坐标系下,直线可以表示为ax + by + c = 0,那么两个半平面则可以表示为ax + by + c >= 0 和ax + by + c < 0,这就是半平面的表示方法. 还有,半平面的交是神马玩意? 其实就是一个方程

POJ 3525 /// 半平面交 模板

题目大意: 给定n,接下来n行逆时针给定小岛的n个顶点 输出岛内离海最远的点与海的距离 半平面交模板题 将整个小岛视为由许多半平面围成 那么以相同的比例缩小这些半平面 一直到缩小到一个点时 那个点就是离海最远的点 #include <cstdio> #include <cmath> #include <vector> #include <algorithm> using namespace std; const double eps=1e-10; doubl