Graham算法解决凸包问题

模板题,题目来自洛谷如下。

圈奶牛【模板】二维凸包

题目简要描述

给定一些点,求凸包的周长。

输入格式

输入数据的第一行是一个整数。表示农夫约翰想要围住的放牧点的数目n。

第 222 到第 (n+1)(n + 1)(n+1) 行,每行两个实数,第 (i+1)(i + 1)(i+1) 行的实数 xi, yi 分别代表第 iii 个放牧点的横纵坐标

输出格式

输出输出一行一个四舍五入保留两位小数的实数,代表围栏的长度。

输入输出样例

//输入
4
4 8
4 12
5 9.3
7 8//输出
12.00

Graham算法

该算法的大致思路为

​ 通过维持一个关于候选点的栈S来解决凸包问题。输入集合Q中的每个点都被压入栈一次,非凸包顶点的点最终被弹出栈。当算法终止时,栈中仅包含凸包顶点,且以逆时针的顺序出现在边界上。而该算法主要由排序扫描组成。(摘自《算法导论》)

主要过程

​ 首先是排序过程,易得纵坐标最小的值必定是凸包中的顶点,因此选择一个y值最小(如有相同选x最小)的点,记作P0。接着其余的点按极角的大小逆时针排序,编号P1至Pm

​ 接着是扫描过程,按上述排序过程遍历每个点,进行判断,如若该点更合适,则上一个点出栈,该点入栈,否则直接入栈。

图片说明:

​ 文字描述比较绕,下面给出图片描述。(图源来自《算法导论》)


代码实现:

#include<bits/stdc++.h>
#define maxn 8000005
using namespace std;
int n;
struct dot{double x;double y;
}p[maxn], s[maxn];  // p用以存所有点,s用以存凸包顶点
double cp(dot a1, dot a2, dot b1, dot b2){ // 叉乘,a1,a2,b1,b2为四个点 return (a2.x - a1.x) * (b2.y - b1.y) - (b2.x - b1.x) * (a2.y - a1.y);
}
double dis(dot p1, dot p2){ //求两点间距 return sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
}
bool cmp(dot p1, dot p2){ // 排序函数,按极角大小排序 double tmp = cp(p[0], p1, p[0], p2);if(tmp > 0) return 1;if(tmp == 0 && dis(p[0], p1) < dis(p[0], p2)) return 1;return 0;
}
int main(){scanf("%d", &n);double tmp;for(int i = 0; i < n; i++){scanf("%lf%lf", &p[i].x, &p[i].y);if(i > 0 && (p[i].y < p[0].y || (p[i].y == p[0].y && p[i].x < p[0].x))){ // p[0].y保证最小 tmp = p[i].x, p[i].x = p[0].x, p[0].x = tmp;tmp = p[i].y, p[i].y = p[0].y, p[0].y = tmp;}}sort(p + 1, p + n, cmp); //从第二项开始排s[0] = p[0]; //p[0]一定在凸包中int cnt = 0;for(int i = 1; i < n; i++){// 判断此时栈顶的点是否需要剔除,这步结合上图可理解的更透彻 while(cnt > 0 && cp(s[cnt - 1], s[cnt], s[cnt], p[i]) <= 0) cnt -= 1;cnt += 1;s[cnt] = p[i]; //p[i]入栈 } s[cnt + 1] = p[0]; //需要求周长, 第一个点再入栈double C = 0;for(int i = 0; i <= cnt; i++)C += dis(s[i], s[i + 1]);printf("%.2lf", C);return 0;
}

Graham算法解决凸包问题相关推荐

  1. graham算法 java_凸包Graham Scan算法实现

    凸包算法实现点集合中搜索凸包顶点的功能,可以处理共线情况,可以输出共线点也可以不输出而只输出凸包顶点.经典的Graham Scan算法,点排序使用极角排序方式,并对共线情况做特殊处理.一般算法是将共线 ...

  2. Graham算法构造凸包(python)

    一.算法步骤 首先找到点集中y坐标最小的点作为初始点p0p_0p0​,若y坐标相同,选取x坐标最小的一个点作为p0p_0p0​ 以p0为原点,对点集进行极角排序得到集合{p0,p1...pn}\lef ...

  3. HDUOJ 1392凸包graham算法

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  4. 凸包问题-Graham 算法

    这里我只是想记录一下凸包问题,我发现如果要把他讲解非常清楚,需要画比较复杂的集合图形,而我不会.所以,这篇文章可能只能帮你梳理一下算法步骤或者参考一下代码. 什么是凸包问题 找一条线,能够将二维平面上 ...

  5. 凸包模板(Graham算法)

    因为某些原因被迫学习几何知识..先从网上拿个模板来用用 用处: 可以按照极角排序,依次找出凸包边界的点 const int N=10;int n=4,tot;struct node {double x ...

  6. 【POJ 2187】如何修改Graham算法,才能使之顺利解决三点一条直线的问题。

    暑期集训中做了 POJ 2187 题,噩梦一场,但是这次仔细把一些 Graham 算法在处理存在三点在一条直线上问题的改进方法找到了. 题目意思很明确:给你平面上的一坨点,求最远两点距离的平方. 思路 ...

  7. 【计算几何】凸包之graham算法(适合小白)

    计算几何–凸包(graham算法实现) 题目链接:LeetCode587 https://leetcode-cn.com/problemset/all/ 题目描述 在一个二维的花园中,有一些用 (x, ...

  8. 凸包Graham算法

    在学习Graham算法前,需要先了解二维叉乘这个概念. 叉乘的拓展 在一般的常识或者教科书中规定叉乘只有3d才拥有,其实2d也可以拓展出来一个叉乘形式,而且非常有用. 拓展方式:假设有两个2d向量a, ...

  9. 分治算法-02凸包问题

    几何问题之凸包 简介 简单地说,凸包是正好包含所有点的凸多边形,可以将它想象为一个包围点几何的橡皮筋.之所以叫凸包是因为这个凸多边形包围所有点.本案例主要讲解分治法解决凸包问题,常见的还有Graham ...

最新文章

  1. matlab“机器学习和深度学习”系列工具箱作用总结
  2. JavaScript中的endsWith
  3. hdu 3183 st表
  4. 字符串原样输出程序python_Python格式化字符串(格式化输出)
  5. 工业机器人码垛教学实施_工业码垛机器人存在问题与解决对策
  6. 【scala】集和映射
  7. Send data format set as XML
  8. 如何进行防SQL注入?
  9. css学习_css3过渡
  10. 【华为云技术分享】#探索鲲鹏#之“在鲲鹏上使用编程语言——C语言
  11. java vector 多线程_如何使用vector解决多线程问题(java)
  12. 苹果的“价格战”还能走多远? | 畅言
  13. 查看mysql单个表大小限制_查看单个mysql数据库中各个表的大小
  14. 鸡啄米vc++2010系列7(对话框:创建对话框类和添加控件变量)
  15. centos源码安装Xen
  16. [境内法规]中国人民银行关于分支行反洗钱工作的指导意见—银发[2005]56号
  17. DICOM笔记-使用DCMTK读取DICOM文件保存DICOM文件
  18. ENVI裁剪遥感图像
  19. 三坐标雷达航迹跟踪与应用
  20. freeradius部署及挑战模式配置

热门文章

  1. 2020年chx的计算机保研之路系列(2)——华东师范大学计算机学院(获得优营)
  2. 无线路由器连接交换机
  3. android小米推送,Android手机端小米推送Demo解析和实现方法
  4. 多个视频合成一个视频(带合成工具)
  5. 惠州生物实验室建设宝典
  6. GameFrameWork框架(Unity3D)使用笔记(八) 实现场景加载进度条
  7. python3.5安装tensorflow_win10下python3.5.2和tensorflow安装环境搭建教程
  8. [iOS][转]iOS 架构模式 - 简述 MVC, MVP, MVVM 和 VIPER (译)
  9. 千亿级服务器监控数据存储实践
  10. Mackbook 外接移动硬盘无法写入数据(三种解决办法)