Convex hull凸包

把一个平面上给出的点都包含进去的最小凸多边形。逆时针输出凸包的各个顶点。

1.Graham扫描法 (O(n*logn))-------旋转扫除的技术:

2.Jarvis march步进法(O(n*h))h为凸包的顶点数--------打包的技术

应用:求二维平面最远点对。

uva,109

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4
  5 using namespace std;
  6
  7 struct node
  8 {
  9     double x,y;
 10     //便于求出初始点
 11     bool operator<(const node& a)const{
 12         return x<a.x || (x==a.x && y<a.y);
 13     }
 14 };
 15
 16
 17 typedef vector<node> Vnode;//凸包
 18 typedef vector<Vnode> VVnode;//凸包个数
 19
 20 //叉积判断是否向左转。
 21 double Isleft(node& p0,node& p1,node& p2)
 22 {
 23     return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
 24 }
 25
 26 //求凸包
 27 int Convex_hull(Vnode p,Vnode &h){
 28     int n=p.size();
 29     int k=0;
 30     //按x升序然后y升序排列
 31     sort(p.begin(),p.end());
 32
 33     for(int i=0;i<n;i++){
 34 //上链
 35         while(k>=2 && Isleft(h[k-2],h[k-1],p[i])<=0)
 36             k--;
 37         h[k++]=p[i];
 38     }
 39     //下链
 40     for(int i=n-2,t=k+1;i>=0;i--){
 41         while(k>=t && Isleft(h[k-2],h[k-1],p[i])<=0)
 42             k--;
 43         h[k++]=p[i];
 44     }
 45     return k;
 46 }
 47 //检查是否在凸多边形内
 48 int check(Vnode h, node p) {
 49     int n = h.size();
 50     int i, j, c = 0;
 51     for (i = 0, j = n-1; i < n; j = i++)
 52         if ((((h[i].y <= p.y) && (p.y < h[j].y)) || ((h[j].y <= p.y) && (p.y < h[i].y))) && (p.x < (h[j].x - h[i].x) * (p.y - h[i].y) / (h[j].y - h[i].y) + h[i].x))
 53             c = !c;
 54     return c;
 55 }
 56 //根据题意求凸包面积
 57 double Area(Vnode p){
 58     int n=p.size();
 59     double s=0;
 60
 61     for(int i=1;i<n;i++){
 62         s+=((p[i-1].x*p[i].y-p[i].x*p[i-1].y))/2;
 63     }
 64     return s;
 65 }
 66
 67
 68 int main()
 69 {
 70     int n;
 71     VVnode hull;
 72
 73     while(cin>>n && n!=-1)
 74     {
 75         Vnode p(n);
 76         for(int i=0;i<n;i++)
 77             cin>>p[i].x>>p[i].y;
 78
 79         Vnode h(n+1);
 80         n=Convex_hull(p,h);
 81         h.resize(n);
 82         hull.push_back(h);
 83     }
 84
 85     node k;
 86     double a=0;
 87     while(cin>>k.x>>k.y){
 88         VVnode::iterator it;
 89         for(it=hull.begin();it<hull.end();it++)
 90         {
 91             if(check(*it,k))
 92             {
 93                 a+=Area(*it);
 94                 hull.erase(it);
 95                 break;
 96             }
 97         }
 98     }
 99 //输出时带两位小数
100     cout.precision(2);
101 //fixed固定格式,floatfield代表以浮点数输出
102     cout.setf(ios::fixed,ios::floatfield);
103     cout<<a<<endl;
104
105     return 0;
106 }

时间: 2024-10-11 13:28:04

Convex hull凸包的相关文章

Computational Geometry PA1 Convex Hull (凸包)

题目链接:http://dsa.cs.tsinghua.edu.cn/oj/problem.shtml?id=710 CG2015 PA1-1 Convex Hull (凸包) Description (描述) After learning Chapter 1, you must have mastered the convex hull very well. Yes, convex hull is at the kernel of computational geometry and serv

Opencv Convex Hull (凸包)

#include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; Mat img1, img2, img3, img4, img_result, img_gray1, img_gray2, img_gray3, img_canny1; char win1[] = "window1";char win2[] = "window2";c

凸包(Convex Hull)构造算法——Graham扫描法

凸包(Convex Hull) 在图形学中,凸包是一个非常重要的概念.简明的说,在平面中给出N个点,找出一个由其中某些点作为顶点组成的凸多边形,恰好能围住所有的N个点. 这十分像是在一块木板上钉了N个钉子,然后用一根绷紧的橡皮筋它们都圈起来,这根橡皮筋的形状就是所谓的凸包. 计算凸包的一个著名算法是Graham Scan法,它的时间复杂度与所采用的排序算法时间复杂度相同,通常采用线性对数算法,因此为\( O\left(N\mathrm{log}\left(N\right)\right) \).

zoj 3871 Convex Hull(凸包)

题目链接:zoj 3871 Convex Hull 枚举每条边,计算出有多少情况下为凸包的边界,即有多少点在该边的左边. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <complex> #include <algorithm> using namespace std; typedef pair<int,int&g

opencv笔记(二十四)——得到轮廓之后找到凸包convex hull

当我们得到一张轮廓之后,我们可以对其运用convexHull方法,寻找该轮廓的凸包. 一个轮廓可以有无数个包围它的外壳,而其中表面积最小的一个外壳,就是凸包. void convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints=true ) points是一个contour. vector<Point>类型或者Mat类型 hull是输出,也是一个点集vector<Poin

Monotone Chain Convex Hull(单调链凸包)

1 Monotone Chain Convex Hull(单调链凸包)算法伪代码: 2 //输入:一个在平面上的点集P 3 //点集 P 按 先x后y 的递增排序 4 //m 表示共a[i=0...m]个点,ans为要求的点; 5 struct P 6 { 7 int x,y; 8 friend int operator < (P a, P b) 9 { 10 if((a.x<b.x) || (a.x==b.x && a.y<b.y)) 11 return 1; 12 r

[算法课][分治]寻找凸包 (Convex Hull)

凸包问题是算法中经典的题目了,最近算法课讲分治问题时提到了Convex Hull,算法导论的书上也花了篇幅讨论了Convex Hull的求解,主要是Graham方法. 为了能更好地理解分治和Graham这两种解法,我决定自己动手把代码写一遍. 然而,在写之前,我发现我大一学的用行列式求解由三个点围城的三角形面积已经忘得差不多了,现在补充一下: 利用这个计算结果来判断点p3在p1p2直线的左侧还是右侧 下面是分治算法求解: #include <iostream> #include <alg

OpenCV入门之寻找图像的凸包(convex hull)

介绍   凸包(Convex Hull)是一个计算几何(图形学)中的概念,它的严格的数学定义为:在一个向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包.  在图像处理过程中,我们常常需要寻找图像中包围某个物体的凸包.凸包跟多边形逼近很像,只不过它是包围物体最外层的一个凸集,这个凸集是所有能包围这个物体的凸集的交集.如下图所示: 在上图中,绿色线条所包围的凸集即为白色图形的凸包.  在opencv中,通过函数convexHulll能很容易的得到一系列点的凸包,比如由点组成的轮廓

凸包问题Finding the convex hull

问题描述:找到包含点集Q的最小凸多边形.使得点集内的点均在凸多边形的边上或内部. 即集合内任意两点的连线均在凸多边形内部. 输入:平面上的n个点的集合Q 输出: CH(Q):Q的convexhull (一)蛮力法思路: 找到点集内的内部点去掉,剩余未边界点. 内部点的判断:只要其中三点A,B,C构成的三角形包含的点P则P为内部点. 三角形内部点具体判断方法: 如果P在△ABC内部,则A,P两个点在BC同侧:P,B两个点在AC同侧:C,P两个点在AB同侧.转换为点与线关系的判断. 判断点P与直线A