计算几何 二维凸包问题 Andrew算法
凸包:把给定点包围在内部的、面积最小的凸多边形。
Andrew算法是Graham算法的变种,速度更快稳定性也更好。
首先把全部点排序。依照第一keywordx第二keywordy从小到大排序,删除反复点后得到点序列P1...Pn。
1)把P1,P2放入凸包中,凸包中的点使用栈存储
2)从p3開始,当下一个点在凸包当前前进方向(即直线p1p2)左边的时候继续;
3)否则依次删除近期增加凸包的点,直到新点在左边。
如图,新点P18在当前前进方向P10P15的右边(使用叉积推断),因此须要从凸包上删除点P15和P10。让P8的下一个点为P18。反复该过程直到碰到最右边的Pn,求出下凸包即凸包的下轮廓。然后从Pn反过来反复该步骤求出上凸包,合并起来后就是完整的凸包。
该算法扫描为O(n)复杂度,排序O(nlogn)。
C++ code(刘汝佳《算法竞赛入门经典-训练指南》模板)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath> using namespace std; const double eps = 1e-8,Pi=3.14159265; int n; inline int dcmp(double x)//三态函数
{
if(fabs(x) < eps) return 0;
else return x>0 ? 1 : -1;
} #define Vector Point
struct Point
{
double x,y;
inline Point(double x=0,double y=0):x(x),y(y) {}
}p[10000+5],ch[10000+5]; bool myCmp(Point A, Point B)
{
if(A.x != B.x) return A.x < B.x;
else return A.y < B.y;
} Vector operator + (Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);}
Vector operator - (Vector A, Vector B) {return Vector(A.x - B.x, A.y - B.y);}
bool operator == (const Vector& A, const Vector& B) {return dcmp(A.x-B.x)==0 && dcmp(A.y-B.y)==0;} inline double Cross(Vector A, Vector B)//叉积
{
return A.x * B.y - A.y * B.x;
} int ConvexHull()
{
sort(p,p+n,myCmp);
int m = 0;
for(int i = 0; i <n; i++)
{
while(m > 1 && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-2; i >= 0; i--)
{
while(m > k && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
return m;
} double Dis(Point A, Point B)
{
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
} int main()
{
int m;
cin>>n;
for(int i = 0; i < n; i++)
{
int a,b;
cin>>a>>b;
p[i] = Point(a,b);
}
m = ConvexHull();
//计算凸包周长
double ans=0.0;
for(int i = 0; i < m-1; i++)
ans += Dis(ch[i],ch[i+1]);
ans += Dis(ch[m-1],ch[0]);
printf("%.1f",ans);
}
例题:
wikioi1298(click me)
求解二维凸包并计算周长
wikioi3201(click me)
求解二维凸包并计算周长
poj1113( id=1113">click me
本题翻译:http://blog.csdn.net/lytning/article/details/24046075
求解二维凸包并增加一个圆的周长
计算几何 二维凸包问题 Andrew算法的更多相关文章
- 二维凸包 Graham扫描算法
题目链接: http://poj.org/problem?id=1113 求下列点的凸包 求得凸包如下: Graham扫描算法: 找出最左下的点,设为一号点,将其它点对一号点连线,按照与x轴的夹角大小 ...
- Andrew算法求二维凸包-学习笔记
凸包的概念 首先,引入凸包的概念: (有点窄的时候...图片右边可能会被吞,拉开图片看就可以了) 大概长这个样子: 那么,给定一些散点,如何快速地求出凸包呢(用在凸包上的点来表示凸包) Andrew算 ...
- 【计算几何】二维凸包——Graham's Scan法
凸包 点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内.右图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包. 一组平面上的点, ...
- Luogu P2742 模板-二维凸包
Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...
- UVA 10652 Board Wrapping(二维凸包)
传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组 ...
- 使用Graham扫描法求二维凸包的一个程序
#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> # ...
- luogu P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows
题解: 二维凸包裸题 按照x坐标为第一关键字,y坐标为第二关键字排序 然后相邻判断叉积用单调队列搞过去 正反都做一次就好了 代码: #include <bits/stdc++.h> usi ...
- 【洛谷 P2742】【模板】二维凸包
题目链接 二维凸包板子..有时间会补总结的. #include <cstdio> #include <cmath> #include <algorithm> usi ...
- poj 2079 Triangle (二维凸包旋转卡壳)
Triangle Time Limit: 3000MS Memory Limit: 30000KB 64bit IO Format: %I64d & %I64u Submit Stat ...
随机推荐
- .net Jquery动态显示当前时间
<span id="Timer"></span> <script type="text/javascript"> $(fun ...
- AdminLTE介绍和zTree的简单使用
一.AdminLTE介绍 1.介绍 AdminLTE是一个开源的后台控制面板和仪表盘 WebApp 模板,是建立在Bootstrap3框架和JQuery之上的开源模板主题工具,它提供了一系列响应的 ...
- windows下关闭进程树
关闭进程需要特定权限,如果你程序权限不够也会导致关闭进程失败.关闭进程树,需要遍历给定进程下的所有子进程,这个过程可以用并查集来做. 1.编写获取进程父进程的代码 #define ProcessBas ...
- python 之 sqlite3
# -*- coding: utf-8 -*- ''' 创建数据库日志,三列为时间 身份证号和备注名''' import os import sys import sqlite3 import dat ...
- python读取单个文件操作
python读取单个文件,参考<笨方法学python>的第15节. 运行方式是采用:python python文件名 要读取的文件名 代码中 script, filename = argv ...
- CSS3:变换和动画
<html> <style> .container{ -webkit-perspective: 800; -webkit-perspective-origin: 50% 40% ...
- wpf绑定静态变量,模拟rem单位
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; usin ...
- linux下如何限制普通用户更改密码
问题描述: 为了方便linux管理员对所有用户的进行管理,如何限制普通用户更改密码? 解决方法: 禁止普通用户更改密码: /usr/bin/passwd 若要允许普通用户更改密码: /usr/bin/ ...
- openstack——cinder服务篇
一.cinder 介绍: 理解 Block Storage 操作系统获得存储空间的方式一般有两种: 通过某种协议(SAS,SCSI,SAN,iSCSI 等)挂接裸硬盘,然后分区.格式化.创建文 ...
- linq排序之 根据文本 A-001-002-003 这种类型进行分割排序 空值放于最后
调用 List<string> data = new List<string>() { "D-001-001-001","A-001-004-00 ...