二维凸包 Graham扫描算法
题目链接:
http://poj.org/problem?id=1113
求下列点的凸包
求得凸包如下:
Graham扫描算法:
找出最左下的点,设为一号点,将其它点对一号点连线,按照与x轴的夹角大小排序:
让点1,2入栈,从第三个点开始循环
步骤1:判断该点是否在栈顶第二个点和栈顶的点的连线的左边,
2.如果在左边,将该点入栈,继续循环,
3.如果不在,弹出栈顶点,重复步骤1,
3在1,2连线左边,3入栈
4在2,3连线左边,4入栈
5不在3,4连线左边,4出栈,5在2,3连线左边,5入栈
6在3,5连线左边,6入栈
7不在5,6连线左边,6出栈,7在3,5连线左边,7入栈
遍历完成后,将栈顶与1连起来就完成了
代码
- //#include<bits/stdc++.h>
- #include<iostream>
- #include<cmath>
- #include<algorithm>
- #define fi first
- #define se second
- #define INF 0x3f3f3f3f
- #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
- #define pqueue priority_queue
- #define NEW(a,b) memset(a,b,sizeof(a))
- #define lowbit(x) ((x)&(-x))
- using namespace std;
- const double pi=4.0*atan(1.0);
- const double e=exp(1.0);
- const int maxn=4e4+;
- typedef long long LL;
- typedef unsigned long long ULL;
- const LL mod=1e9+;
- const ULL base=1e7+;
- struct Point{
- int x,y;
- bool operator<(Point &u){//坐标排序
- if(x!=u.x) return x<u.x;
- return y<u.y;
- }
- };
- Point vex[maxn],Stack[maxn],Basis;
- short checkL(Point p,Point q,Point s){//判断点s是否在直线pq的左侧
- int area2=p.x*q.y-p.y*q.x+q.x*s.y-q.y*s.x+s.x*p.y-s.y*p.x;
- if(area2>) return ;//表示在左侧
- if(area2==) return ;//表示在同一条线上;
- return -;//表示在右侧
- }
- double dis(Point u,Point v){//计算uv的距离
- return sqrt((u.x-v.x)*(u.x-v.x)*1.0+(u.y-v.y)*(u.y-v.y));
- }
- bool cmp(Point a,Point b){//极角排序
- short m=checkL(Basis,a,b);
- if(m==) return ;//b在基点与a的连线的左侧,说明b的极角大于a
- if(m==&&dis(Basis,a)<=dis(Basis,b))//极角相同时,靠近基点的排在前
- return ;
- return ;
- }
- int main(){
- cin.tie();
- cout.tie();
- int n,l;
- cin>>n>>l;
- for(int i=;i<n;i++){
- cin>>vex[i].x>>vex[i].y;
- }
- sort(vex,vex+n);
- Basis=vex[];//选第一个点为基点
- sort(vex+,vex+n,cmp);
- int top=;
- Stack[top]=vex[];
- Stack[++top]=vex[];
- for(int i=;i<n;i++){
- while(top>=&&checkL(Stack[top-],Stack[top],vex[i])<){
- top--;
- }
- Stack[++top]=vex[i];
- }
- double sum=0.0;
- for(int i=;i<top;i++){
- sum+=dis(Stack[i],Stack[i+]);
- }
- sum+=dis(Stack[top],Stack[]);
- sum+=2.0*pi*l;
- LL ans=(LL)sum;
- if(sum-(double)ans>=0.5){
- ans++;
- }
- cout<<ans<<endl;
- system("pause");
- return ;
- }
二维凸包 Graham扫描算法的更多相关文章
- 【计算几何】二维凸包——Graham's Scan法
凸包 点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内.右图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包. 一组平面上的点, ...
- 计算几何 二维凸包问题 Andrew算法
凸包:把给定点包围在内部的.面积最小的凸多边形. Andrew算法是Graham算法的变种,速度更快稳定性也更好. 首先把全部点排序.依照第一keywordx第二keywordy从小到大排序,删除反复 ...
- Andrew算法求二维凸包-学习笔记
凸包的概念 首先,引入凸包的概念: (有点窄的时候...图片右边可能会被吞,拉开图片看就可以了) 大概长这个样子: 那么,给定一些散点,如何快速地求出凸包呢(用在凸包上的点来表示凸包) Andrew算 ...
- 使用Graham扫描法求二维凸包的一个程序
#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> # ...
- POJ 2187 旋转卡壳 + 水平序 Graham 扫描算法 + 运算符重载
水平序 Graham 扫描算法: 计算二维凸包的时候可以用到,Graham 扫描算法有水平序和极角序两种. 极角序算法能一次确定整个凸包, 但是计算极角需要用到三角函数,速度较慢,精度较差,特殊情况较 ...
- Luogu P2742 模板-二维凸包
Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...
- android 二维码生成+扫描
android 二维码生成+扫描 1.在Android应用当中,很多时候都要用到二维码扫描,来避免让用户手动输入的麻烦. Google官方自己推出了一个二维码开源项目:ZXing库. 2.这里简单介绍 ...
- UVA 10652 Board Wrapping(二维凸包)
传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组 ...
- ios中二维码的使用之二: 二维码的扫描
二维码的扫描: 1,导入支持框架,<AVFoundation/AVFoundation.h> 2 ,扫描:
随机推荐
- linux 命令失效
失效的原因 是我在执行命令的时候输入错误了.在网上找了很多的办法都是以下两种方式: 其一:直接在linux命令行界面输入如下,然后回车(导入环境变量,以及shell常见的命令的存放地址): exp ...
- vue调用支付接口
html: <div class="paymentHtml" v-html="paymentHtml"></div> script: d ...
- XML二
XML的语法要求: 1,XML文档必须有一个顶层元素,即文档元素,所有其他元素必须嵌入在文档元素中. 2,元素嵌套要正确,即如果一个元素在另一个元素中开始,那么必须在同一个元素中结束. 3,每个元素必 ...
- Processing 编程学习指南 (丹尼尔·希夫曼 著)
https://processing.org/reference/ 第1章 像素 (已看) 第2章 Processing (已看) 第3章 交互 (已看) 第4章 变量 (已看) 第5章 条件语句 ( ...
- centos7以rpm方法装mysql5.7及大坑
环境: CentOS Linux release 7.5.1804 (Core) Mysql版本: MySQL-5.7.17-1.el6.x86_64.rpm-bundle.tar 下载地址( ...
- windos下安装django
一:pip install Django 安装完以后,运行python manager.py runserver 0.0.0.0:8000报错: 1):没有安装Mysql-python ...
- exactly-once和kafka
Exactly-Once的概念是指"恰好一次",简单讲就是同一个数据只会被处理一次,应用有机质保证不会重复处理同一条数据(如果数据因为因为网络业务异常被发送多次):Exactly- ...
- Java面试题 Web+EJB & Spring+数据结构& 算法&计算机基础
六.Web 部分:(共题:基础40 道,基础37 道,中等难度3 道) 122.说出Servlet 的生命周期,并说出Servlet 和CGI 的区别? [基础] 答:Web 容器加载Servlet ...
- sync;sync;sync;reboot
Sync命令 在用reboot命令启动unix系统后,系统提示出错信息,部分应用程序不能正常工作.经仔细检查系统文件,并和初始的正确备份进行比较,发现某些文件确实被破坏了,翻来覆去找不到文件遭破坏的原 ...
- Git分支merge和rebase的区别
Git merge是用来合并两个分支的. git merge b # 将b分支合并到当前分支 同样 git rebase b,也是把 b分支合并到当前分支 原理 如下: 假设你现在基于远程分支&quo ...