凸包 graham 算法

标签: 算法distancexpstructoutputinput
2011-09-08 12:30 8371人阅读 评论(2) 收藏 举报
 分类:
c++ 凸包 graham

版权声明:本文为博主原创文章,未经博主允许不得转载。

向量:

1.向量的内积(数量积,点乘):

公式:a· b = |a| * |b| cos<a, b>=a.x* b.y + b.x * a.y

2.向量的外积(向量积,差乘):

公式:|c|= |a|*|b|*sin<a, b> = a.x * b.y - b.x * a.y

意义:

1).两个向量和坐标原点所围成的面积(可正可负)。

2).值为正值表示向量a在向量b的顺时针方向,反之,向量a在向量b的逆时针方向,相等时,共线.

凸包:由平面上的最小点所围成的多边形,平面上任何其它的点都在这个多边形内部,这个多边形就称为

凸包。

                                         (图1) 

graham算法:

第一步:选取x轴坐标最小的点,如果存在多个选y轴坐标最小的点.(如图1,p0点)

第二步:排序.从下到上扫描有其它点.(如图1)扫描的结果顺序,p0, p4, p5, p7, p9,p6, p8, p2,p3, p1.

数学公式向量的外积模公式:|c|(是模不是绝对值符号)= |a|*|b|*sin<a, b> = a.x * b.y – b.x * a.y

|c|> 0:向量a在向量b的顺时针方向,因为此例原点坐标取x轴坐标最小的点,所以,向量a在向

量b的下方.(p0-p4线段在p0-p5的下方).

|c|= 0:共线时,按照与原点距离由小到大的顺序.

第三步:按照第二步得到的顶点顺序进行graham扫描.按照本例选取的原点方式,当扫描到左拐(p0,p4, p5)时保留(p4),右拐(p9,p6, p8)时删除顶点(p6),结果就是凸包的顶点集.(绿线扫描的顺序,红线为左拐点).共线时,删除距离较小的点.

注意:右拐删除结点时,必须回溯与前面保留的点重新比较,因为删除一个点后先前拐点性质会发生变化

例如:删除p6后,(p7, p9, p8) 也是右拐了.

所谓的左拐/右拐就沿着边界扫描后,其它的点是否在当前点与下一点连线与原点的内部.

例如:结果p7-p8是凸包的顶点,p7-p8直线会把所有其它点挡在原点p0方向的一侧.

数学公式:

向量外积模公式

例:

p5– p4向量Xp0 – p4 向量>0, (p5–p4)在(p0–p4)的顺时针方向,左拐

p8– p6向量Xp9 – p6向量<0, (p8–p6)在(p9–p6)的逆时针方向,右拐

也可以采用其它向量方式

:

p4–p0向量Xp5–p0向量>0, (p4–p0)在(p5–p0)的顺时针方向,左拐

p6–p9向量Xp8–p9向量<0, (p6–p9)在(p8–p9)的逆时针方向,右拐

示例程序:

p0:(1, -2)

p1:(1, 2)

p2:(5, 3)

p3:(4,5)

p4:(2, -4)

p5:(6, -6)

p6:(7, 0)

p7:(10, -3)

p8:(9, 4)

p9:(8, -1)

input:

10

1 -2

1 2

5 3

4 5

2 -4

6 -6

7 0

10-3

9 4

8 -1

output:

1 -2

2 -4

6 -6

10-3

9 4

4 5

1 2

源代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <fstream>

#define MAX_NUMS 10

typedef struct
{
    int x;
    int y;
} veritice;

veritice   vet[MAX_NUMS];
int                   n;
std::vector<veritice>  v;

inline int cross(const veritice& p0, const veritice& p1, const veritice& p2)
{
    veritice u, v;

u.x = p1.x - p0.x, u.y = p1.y - p0.y;
    v.x = p2.x - p0.x, v.y = p2.y - p0.y;

return v.x * u.y - u.x * v.y;
}

inline int distance(const veritice& p1, const veritice& p2)
{
    return (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
}

inline int graham_compare(const void* a, const void* b)
{
    int result = cross(vet[0], *(veritice*)a, *(veritice*)b);

if(result)
        return result;

return distance(vet[0], *(veritice*)a) - distance(vet[0], *(veritice*)b);
}

inline void graham_scan()
{
    v.push_back(vet[0]);
    v.push_back(vet[1]);

for(int i = 2; i < n; i++)
    {
        while( cross(v[v.size() - 1], v[v.size() - 2], vet[i]) <= 0)
            v.pop_back();

v.push_back(vet[i]);
    }
}

int main()
{
    std::ifstream in("case_in");
    int index = 0;

in >> n;

for(int i = 0; i < n; i++)
    {
        in >> vet[i].x >> vet[i].y;

if(vet[0].x > vet[i].x || (vet[0].x == vet[i].x && vet[0].y > vet[i].y))
            index = i;
    }

in.close();
// 第一步
    veritice temp;
    temp.x       = vet[0].x,       temp.y       = vet[0].y;
    vet[0].x     = vet[index].x,   vet[0].y     = vet[index].y;
    vet[index].x = temp.x,         vet[index].y = temp.y;

// 第二步
    qsort(vet + 1, n - 1, sizeof(veritice), graham_compare);

// 第三步
    graham_scan();

//  输出
    for(unsigned int i = 0; i < v.size(); i++)
        std::cout << v[i].x << ' ' << v[i].y << std::endl;

return 0;
}

写到usaco上的一题可能题解是凸包所以转来这篇文章看看相关推荐

  1. 上哪里可以找到漂亮的思维导图模板?这篇文章告诉你答案

    如今,思维导图的运用越来越普遍了,它的制作已不仅限于个人学习的使用,还融入到了办公生活和岗位技能要求中,许多公司在工作中会要求员工上交对于某个产品等制作.推广的方案,这个方案需要加以思维导图作为辅助资 ...

  2. C++面试常见问答题看这三篇文章就够了(上)

    目录 1. 标识符的组成结构 2. 动态关联和静态关联的区别 3.  重载(overload)和重写(overried)的区别 4. class和struct的区别 5. 构造方法的特点 6. 面向对 ...

  3. 蓝桥杯真题 13省2-马虎的算式 小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。 有一次,老师出的题目是:36 x 495 = ? 他却给抄成了:396 x 45 = ? 但结果却

    问题描述 小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了. 有一次,老师出的题目是:36 x 495 = ? 他却给抄成了:396 x 45 = ? 但结果却很戏剧性,他的答案竟然是对的 ...

  4. c语言编程 六个评委打分,有人知道这怎么写吗?谢谢程序填空题,下面程序的功能是 9 个...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 有人知道这怎么写吗?谢谢 程序填空题,下面程序的功能是 9 个评委给某个参赛选手打分,去掉一个最高分和一个 最低分,求该参赛选手的平均分. #includ ...

  5. verilog练习:hdlbits网站上的做题笔记(6)

    前言 之前的文章<如何学习verilog,如何快速入门?>中提到了verilog学习,推荐了一个可以练习的网站:hdlbits网站,那自己也玩玩这个网站. 这篇文章,是接着<veri ...

  6. verilog练习:hdlbits网站上的做题笔记(5)

    前言 之前的文章<如何学习verilog,如何快速入门?>中提到了verilog学习,推荐了一个可以练习的网站:hdlbits网站,那自己也玩玩这个网站. 这篇文章,是接着<veri ...

  7. verilog练习:hdlbits网站上的做题笔记(7)!强烈推荐!

    前言 之前的文章<如何学习verilog,如何快速入门?>中提到了verilog学习,推荐了一个可以练习的网站:hdlbits网站,那自己也玩玩这个网站. 这篇文章,是接着<veri ...

  8. verilog练习:hdlbits网站上的做题笔记(8)

    前言 之前的文章<如何学习verilog,如何快速入门?>中提到了verilog学习,推荐了一个可以练习的网站:hdlbits网站,那自己也玩玩这个网站. 这篇文章,是接着<veri ...

  9. Python 在Online Judge上自动挂题脚本

    Pre-Reading: 学弟搭建的开源OJ-青岛大学OJ 想了一下大概凡是用这个开源项目的基本上可以用这个脚本吧. 脚本用的是python的selenium(自动化测试工具) 关于安装seleniu ...

最新文章

  1. linux删除项目命令,项目2 Linux基本命令
  2. python可视化lassocv特征筛选之后的特征的相关性分析热力图
  3. Go Reflect
  4. Linux2.6内核中链表的实现
  5. linux——系统排错之引导恢复shell
  6. Java8 新特性lambda表达式(一)初始
  7. 混乱的MVC,.NET非要MVC不可么?
  8. python实现归并算法
  9. ftl有三种映射地址_FTL地址映射的方法及装置与流程
  10. JAVA集成华为推送 服务端
  11. 2022年API接口零代码、低代码、纯代码开发的框架推荐
  12. 二叉树模型matlab实现,利用Matlab实现二叉树的树形显示
  13. visio 去除“讨厌”的自动捕捉
  14. 新联盟呼吁结束种族主义人工智能研究,声称将面Kong与犯罪行为相匹配
  15. 如何用电脑下载网页中的视频?
  16. java duration 时间差_Java Duration toDays()用法及代码示例
  17. C语言编程练习之水仙花数
  18. 自适应移动端网页显示
  19. 【xgboost】XGBoost
  20. 猎豹掌门人出走,傅盛的“梦游”该醒醒了

热门文章

  1. 使用JS/Jquery获得父窗口的几个方法(笔记)
  2. 2022-2028年中国TAC薄膜行业市场全景评估及投资前景规划报告
  3. OpenCV 笔记(08)— 二维点、三维点、基于 Mat 的 std::vector 等常用数据结构的定义和输出
  4. linux watch命令
  5. vim中tab键8空格换4空格
  6. 浅谈Transformer 及Attention网络
  7. 正则表达式中?=和?:和?!的理解
  8. LeetCode简单题之最后一块石头的重量
  9. LeetCode简单题之重塑矩阵
  10. nvGRAPH API参考分析(二)