水平序 Graham 扫描算法:

计算二维凸包的时候可以用到,Graham 扫描算法有水平序和极角序两种。

极角序算法能一次确定整个凸包,

但是计算极角需要用到三角函数,速度较慢,精度较差,特殊情况较多。

水平序算法需要扫描两次,但排序简单,讨论简单,不易出错。

【算法流程】

1.对顶点按x为第一关键字,y为第二关键字进行排序。

2.准备一个空栈,并将前两个点压入栈。

3.对于每一个顶点A,只要栈顶中还至少两个顶点,记栈顶为T,栈中第二个为U。

若UT(向量) * TA(向量) <= 0, 则将T弹出。重复此过程。

4.直到上一步不再弹出顶点,将A压入栈。扫描完一遍之后得到凸包的下凸壳

5.将点集倒过来再进行一次,得到凸包的上凸壳,组合起来即可。

【算法的时间复杂度】

算法的瓶颈在排序,所以时间复杂度是 O(N log N)。 若坐标均为整数,可以用基数排序将复杂度优化到 O(N)。

贴上代码了~:

//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#define Abs(x) (((x) > 0) ? (x) : (-(x)))
using namespace std; const int INF = 0x3f3f3f3f;
const int MAXN = ;
const double eps = 1e-; struct POINT{
int x;
int y;
POINT() : x(), y() {};
POINT(double _x_, double _y_) : x(_x_), y(_y_) {};
}; bool operator < (const POINT & l, const POINT & r){
return l.y < r. y || (l.y == r.y && l.x < r.x);
} int Cross(const POINT & a, const POINT & b, const POINT & o){
return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
} int SquareDis(POINT a, POINT b){
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
} int Graham(POINT *pnt, POINT *res, int n){
int i, len, top =;
sort(pnt, pnt + n);
if (n == )
return ;
res[] = pnt[];
if (n == )
return ;
res[] = pnt[];
if (n == )
return ;
res[] = pnt[];
for (i =; i < n; i++){
while (top && Cross(pnt[i], res[top], res[top -]) >= )
top--;
res[++top] = pnt[i];
}
len = top;
res[++top] = pnt[n -];
for (i = n -; i >=; i--){
while (top != len && Cross(pnt[i], res[top], res[top -]) >= )
top--;
res[++top] = pnt[i];
}
return top;
} int rotating_calipers(POINT *ch, int n){
int q =, ans =;
ch[n] = ch[];
for (int i = ; i < n; ++i){
while (Cross(ch[i + ], ch[q + ], ch[i]) > Cross(ch[i + ], ch[q], ch[i]))
q = (q +) % n;
ans = max(ans, max(SquareDis(ch[i], ch[q]), SquareDis(ch[i + ], ch[q + ])));
}
return ans;
} int main(){
POINT pnt[MAXN], res[MAXN];
int n;
while(EOF != scanf("%d",&n)){
for (int i = ; i < n; i++)
scanf("%d%d", &pnt[i].x, &pnt[i].y);
int count = Graham(pnt, res, n);
int ans = rotating_calipers(res, count);
printf("%d\n", ans);
}
return ;
}

POJ 2187 旋转卡壳 + 水平序 Graham 扫描算法 + 运算符重载的更多相关文章

  1. Poj 2187 旋转卡壳

    Poj 2187 旋转卡壳求解 传送门 旋转卡壳,是利用凸包性质来求解凸包最长点对的线性算法,我们逐渐改变每一次方向,然后枚举出这个方向上的踵点对(最远点对),类似于用游标卡尺卡着凸包旋转一周,答案就 ...

  2. 二维凸包 Graham扫描算法

    题目链接: http://poj.org/problem?id=1113 求下列点的凸包 求得凸包如下: Graham扫描算法: 找出最左下的点,设为一号点,将其它点对一号点连线,按照与x轴的夹角大小 ...

  3. poj 2079(旋转卡壳求解凸包内最大三角形面积)

    Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 9060   Accepted: 2698 Descript ...

  4. [poj1113][Wall] (水平序+graham算法 求凸包)

    Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall ...

  5. poj 3608(旋转卡壳求解两凸包之间的最短距离)

    Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9768   Accepted: ...

  6. Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

    \(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接 ...

  7. POJ 3608 旋转卡壳

    思路: 旋转卡壳应用 注意点&边  边&边  点&点 三种情况 //By SiriusRen #include <cmath> #include <cstdi ...

  8. poj 3608 旋转卡壳求不相交凸包最近距离;

    题目链接:http://poj.org/problem?id=3608 #include<cstdio> #include<cstring> #include<cmath ...

  9. POJ C++程序设计 编程题#3 编程作业—运算符重载

    编程题 #3 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 写一个二维数组 ...

随机推荐

  1. A Byte of Python (1)安装和运行

    有两种方式构建软件设计:一种是把软件做得很简单以至于明显找不到缺陷:另一种是把它做得很复杂以至于找不到明显的缺陷. ——C.A.R. Hoare 获得人生中的成功需要的专注与坚持不懈多过天才与机会. ...

  2. Android UiAutomator 自动化测试环境搭建---新手1

    1.首先需要准备的工具有 1.java jdk 2. android开发工具 adt 3.ant 安装包(如果下载adt里面有) 2.首先安装java环境,jdk这个百度就可以了. 3.android ...

  3. 一个Sqrt函数引发的血案(转)

    作者: 码农1946  来源: 博客园  发布时间: 2013-10-09 11:37  阅读: 4556 次  推荐: 41   原文链接   [收藏]   好吧,我承认我标题党了,不过既然你来了, ...

  4. SQL中采用Newtonsoft.Json处理json字符串

    原文 SQL中采用Newtonsoft.Json处理json字符串 使用环境: SQL Server2005; VS2010; 关于SQL中部署CLR程序集的方法,网上一搜一大把,需要了解的自行查阅, ...

  5. podoWeb极品流氓软件

    用firefox做页面网络性能测试, 打开网页就会发现页面不停的去请求googleapi.com上的jquery Or swfobject.js,页面就此卡住,一直在等待类似这两个请求的返回,知道Ab ...

  6. VC++6.0中各种文件的作用

    VC++ 6.0是一款很经典的C/C++开发工具,虽然是1998年的东西了,但是现在使用依然很广!在用它开发的时候,会发现在建立的工程的文件夹里面,有很多文件,各种后缀名.在这里呢,我主要说一下各个文 ...

  7. Happy Matt Friends(dp)

    Happy Matt Friends Time Limit: 6000/6000 MS (Java/Others)    Memory Limit: 510000/510000 K (Java/Oth ...

  8. block 解析 - 成员变量

    回顾 在 上一篇 中我们讲了截获变量特性,对于局部变量,变量不加__block修饰符,在block内部是无法修改变量的值.而且 对值类型的修改,如果block初始化后,无法同步到block内部 对于指 ...

  9. [译]Stairway to Integration Services Level 5 - 增量删除数据

    在 dbo.Contact中添加一行记录 Use AdventureWorks go Insert Into dbo.Contact (FirstName, MiddleName, LastName, ...

  10. xocde7下导入libsqlite3.tbd编译报错的解决办法

    在xocde7下没有libsqlite3.dylib,只有libsqlite3.tbd,然后我导入了tbd.编译报错error: /Applications/Xcode.app/Contents/De ...