计算几何-凸包
来源:互联网 发布:相扑在日本的地位 知乎 编辑:程序博客网 时间:2024/05/17 08:22
点集Q的凸包是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内
如下图所示,点集Q={p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13},则Q的凸包为{p1,p5,p7,p12,p13}
Graham扫描法
原理:从已知的点集Q中先找出一个最左下的点(该点必定在凸包上),然后以该点为起点,将所有点按照与这点的斜率的大小排序,然后依次遍历所有点,如果新加入的点是在原方向上向右拐的,就把前一个点去掉(注意是前一个点,而且这一步是要循环执行的)
当遍历完所有点后,还在栈中的点就是凸包上的点了,依次出栈可以得到从起点开始逆时针旋转的所有凸包上的点
步骤:1.找点 2.排序 3.扫描
#include <iostream>#include <set>#include <map>#include <stack>#include <cmath>#include <queue>#include <cstdio>#include <bitset>#include <string>#include <vector>#include <iomanip>#include <cstring>#include <algorithm>#include <functional>#define inf 0x3f3f3f3f#define debug(x) cout<<"---"<<x<<"---"<<endltypedef long long ll;using namespace std;const double eps = 1e-8;const double PI = acos(-1.0);int sgn(double x){ if (fabs(x) < eps) { return 0; } if (x < 0) { return -1; } else { return 1; }}struct Point{ double x, y; Point() {} Point(double _x, double _y) { x = _x; y = _y; } Point operator -(const Point &b)const { return Point(x - b.x, y - b.y); } //叉积 double operator ^(const Point &b)const { return x * b.y - y * b.x; } //点积 double operator *(const Point &b)const { return x * b.x + y * b.y; } //绕原点旋转角度B(弧度值),后x,y的变化(逆时针) void transXY(double B) { double tx = x, ty = y; x = tx * cos(B) - ty * sin(B); y = tx * sin(B) + ty * cos(B); }};//*两点间距离double dist(Point a, Point b){ return sqrt((a - b) * (a - b));}/** 求凸包,Graham算法* 点的编号0~n-1* 返回凸包结果Stack[0~top-1]为凸包的编号*/const int MAXN = 100010;Point list[MAXN];int Stack[MAXN], top;//相对于list[0]的极角排序bool _cmp(Point p1, Point p2){ double tmp = (p1 - list[0]) ^ (p2 - list[0]); if (sgn(tmp) > 0) { return true; } else if (sgn(tmp) == 0 && sgn(dist(p1, list[0]) - dist(p2, list[0])) <= 0) { return true; } else { return false; }}void Graham(int n){ Point p0; int k = 0; p0 = list[0]; //找最下边的一个点 for (int i = 1; i < n; i++) { if ( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) ) { p0 = list[i]; k = i; } } swap(list[k], list[0]); sort(list + 1, list + n, _cmp); if (n == 1) { top = 1; Stack[0] = 0; return; } if (n == 2) { top = 2; Stack[0] = 0; Stack[1] = 1; return ; } Stack[0] = 0; Stack[1] = 1; top = 2; for (int i = 2; i < n; i++) { while (top > 1 && sgn((list[Stack[top - 1]] - list[Stack[top - 2]]) ^ (list[i] - list[Stack[top - 2]])) <= 0) { top--; } Stack[top++] = i; }}int main(){ int t; cin >> t; while (t--) { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> list[i].x >> list[i].y; } Graham(n); cout << top << endl; for (int i = 0; i < top; i++) { cout << list[Stack[i]].x << " " << list[Stack[i]].y << endl; } } return 0;}
阅读全文
0 0
- 计算几何-凸包
- [计算几何]凸包算法
- 计算几何之凸包
- 计算几何-凸包问题
- 计算几何 --- 凸包 模板
- 计算几何凸包详解
- 计算几何中的凸包计算
- 计算几何__凸包算法
- [计算几何]凸包算法 收藏
- [计算几何-凸包]pku1113-Wall
- 计算几何 Graham_scan凸包 pku 1113
- POJ 1113 WALL(凸包-计算几何)
- 计算几何__凸包算法
- poj 1113 计算几何 凸包
- 计算几何——凸包
- 计算几何-经典算法-凸包
- 计算几何-经典算法-凸包
- 计算几何-经典算法-凸包
- linux操作系统体系
- Ajax 技术和框架,叙述框架区别
- 基于Predix平台开发微服务应用需要服务发现框架么?
- 【BZOJ4562】【拓扑排序】【DP】[Haoi2016]食物链 题解
- 线段树 乌鸦喝水
- 计算几何-凸包
- 最简洁易懂的最大子矩阵问题(极大化思想)
- 数据结构示意图
- 设置100%却无法铺满屏幕
- terminator 安装与配置
- IO基础(3)-IO对象流用法
- 多线程知识点总结(一)
- 深度学习 检测模型对比
- Luogu P3040 贝尔分享Bale Share