(模板)poj1113(graham扫描法求凸包)
题目链接:https://vjudge.net/problem/POJ-1113
题意:简化下题意即求凸包的周长+2×PI×r。
思路:用graham求凸包,模板是kuangbin的,算法复杂度O(nlogn)。
AC code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std; const int maxn=;
const double PI=acos(-1.0); struct Point{
int x,y;
Point():x(),y(){}
Point(int x,int y):x(x),y(y){}
}list[maxn];
int stack[maxn],top; //计算叉积p0p1×p0p2
int cross(Point p0,Point p1,Point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
//计算p1p2的距离
double dis(Point p1,Point p2){
return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
//极角排序函数,角度相同则距离小的在前面
bool cmp(Point p1,Point p2){
int tmp=cross(list[],p1,p2);
if(tmp>) return true;
else if(tmp==&&dis(list[],p1)<dis(list[],p2)) return true;
else return false;
}
//输入,把最左下角放在list[0],并且进行极角排序
void init(int n){
Point p0;
scanf("%d%d",&list[].x,&list[].y);
p0.x=list[].x;
p0.y=list[].y;
int k=;
for(int i=;i<n;++i){
scanf("%d%d",&list[i].x,&list[i].y);
if((p0.y>list[i].y)||((p0.y==list[i].y)&&(p0.x>list[i].x))){
p0.x=list[i].x;
p0.y=list[i].y;
k=i;
}
}
list[k]=list[];
list[]=p0;
sort(list+,list+n,cmp);
}
//graham扫描法求凸包,凸包顶点存在stack栈中
//从栈底到栈顶一次是逆时针方向排列的
//如果要求凸包的一条边有2个以上的点
//那么要将while中的<=改成<
//但这不能将最后一条边上的多个点保留
//因为排序时将距离近的点排在前面
//那么最后一条边上的点仅有距离最远的会被保留,其余的会被出栈
//所以最后一条边需要特判
//如果要求逆凸包的话需要改cmp,graham中的符号即可
void graham(int n){
if(n==){
top=;
stack[]=;
return;
}
top=;
stack[]=;
stack[]=;
for(int i=;i<n;++i){
while(top>&&cross(list[stack[top-]],list[stack[top]],list[i])<=) --top;
stack[++top]=i;
}
}
int main(){
int n,r;
scanf("%d%d",&n,&r);
init(n);
graham(n);
double res=*PI*r;
for(int i=;i<top;++i)
res+=dis(list[stack[i]],list[stack[i+]]);
res+=dis(list[stack[]],list[stack[top]]);
printf("%d\n",(int)(res+0.5));
int ans=0;
//叉积求凸包面积
//for(int i=0;i<top;++i)
//ans+=cross(Point(0,0),list[stack[i]],list[stack[i+1]]);
//ans+=cross(Point(0,0),list[stack[top]],list[stack[0]]);
//ans/=2;
return ;
}
题目链接:https://www.luogu.com.cn/problem/P2742
题意:求凸包的周长。
思路:
这里用andrew算法来求,该算法与graham的区别是排序方法不一样,这里按x坐标从左到右排序,x相同的按y坐标从下到上排序。下列程序展示先求下凸包,再求上凸包。复杂度O(nlogn),但据说比graham的复杂度小一点。
AC code:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std; const int maxn=1e5+; struct Point{
double x,y;
Point(double xx=,double yy=):x(xx),y(yy){}
}; double cross(Point p0,Point p1,Point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
//排序方法不同
bool cmp(Point a,Point b){
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y; //y从小到大和从大到小都行
} double dis(Point a,Point b){
return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
} Point list[maxn],stk[maxn];
int n,p;
double ans; void andrew(){
p=;
stk[]=list[],stk[]=list[];
for(int i=;i<n;++i){ //求下凸包
while(p>&&cross(stk[p-],stk[p],list[i])<=)
--p;
stk[++p]=list[i];
}
stk[++p]=list[n-];
for(int i=n-;i>=;--i){ //求上凸包
while(p>&&cross(stk[p-],stk[p],list[i])<=)
--p;
stk[++p]=list[i];
} //要注意栈尾和栈顶都是list[0]
} int main(){
scanf("%d",&n);
for(int i=;i<n;++i)
scanf("%lf%lf",&list[i].x,&list[i].y);
sort(list,list+n,cmp);
andrew();
for(int i=;i<p;++i)
ans+=dis(stk[i],stk[i+]);
printf("%.2f\n",ans);
return ;
}
(模板)poj1113(graham扫描法求凸包)的更多相关文章
- 关于graham扫描法求凸包的小记
1.首先,凸包是啥: 若是在二维平面上,则一般的,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点. ───────────────────────────── ...
- Graham扫描法 --求凸包
前言: 首先,什么是凸包? 假设平面上有p0~p12共13个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来.当这个多边形是凸多边形的时候,我们就叫它“凸包”.如下图: 然后,什么是凸包 ...
- (模板)graham扫描法、andrew算法求凸包
凸包算法讲解:Click Here 题目链接:https://vjudge.net/problem/POJ-1113 题意:简化下题意即求凸包的周长+2×PI×r. 思路:用graham求凸包,模板是 ...
- 使用Graham扫描法求二维凸包的一个程序
#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> # ...
- Graham 扫描法找凸包(convexHull)
凸包定义 通俗的话来解释凸包:给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点  Graham扫描法 由最底的一点 \(p_1\) 开始(如果有多个这样的点, ...
- nyoj-78-圈水池(Graham算法求凸包)
题目链接 /* Name:nyoj-78-圈水池 Copyright: Author: Date: 2018/4/27 9:52:48 Description: Graham求凸包 zyj大佬的模板, ...
- [BZOJ1069][SCOI2007]最大土地面积(水平扫描法求凸包+旋转卡壳)
题意:在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成. 的多边形面积最大.n<=2000. 先求凸包,再枚举对角线,随着对角线的斜率上升,另外两 ...
- [poj1113][Wall] (水平序+graham算法 求凸包)
Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall ...
- POJ-1113 Wall 计算几何 求凸包
题目链接:https://cn.vjudge.net/problem/POJ-1113 题意 给一些点,求一个能够包围所有点且每个点到边界的距离不下于L的周长最小图形的周长 思路 求得凸包的周长,再加 ...
随机推荐
- 【説明する】hash
首先对于判重,我们能想到的方法有什么呢? 1)bool数组 2)set(集) 数组与集合的优缺点: 1.因为集合是对数组做的封装,所以,数组永远比任何一个集合要快. 2.数组声明了它容纳的元素的类型, ...
- linux系列(六):rmdir命令
1.命令格式: rmdir [选项] 目录名 2.命令功能: 该命令从一个目录中删除一个或多个子目录项,删除某目录时也必须具有对父目录的写权限. 3.命令参数: - p 删除指定目录后,若该目录的上层 ...
- fft,ntt总结
一个套路:把式子推成卷积形式,然后用fft或ntt优化求解过程. fft的扩展性不强,不可以在fft函数里多加骚操作--DeepinC T1:多项式乘法 板子题 T2:快速傅立叶之二 另一个板子,小技 ...
- P1021 邮票面值设计——搜索+完全背包
P1021 邮票面值设计 题目意思是你最多用n张邮票,你可以自己设定k种邮票的面值,每种邮票数量无穷,你最多能用这k种邮票在不超过n张的情况下,组合成的价值要求是从1开始连续的, 求最大能连续到多少: ...
- mui Picker DtPicker 固定内容以及变动内容Picker 不同情况下的应用 提高效率
目的是: 保证不同的Picker只创建一次,多次创建Picker系统不会自己销毁,X掉一个之后后面可能会出现下一个. 保证实现需求的情况下,优化代码,提高效率. 1.如果picker中的内容为定值 v ...
- Js 之常见手势操作插件 Hammer.js
一.下载 链接:https://pan.baidu.com/s/1UbEtSbT1xcmdzzTCaWmW1A提取码:ldqy 二.案例 三.代码 <!DOCTYPE html> < ...
- 怎么样使用vuex
https://www.cnblogs.com/songrimin/p/7815850.html
- 深入理解JVM虚拟机6:深入理解JVM类加载机制
深入理解JVM类加载机制 简述:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 下面我们具体 ...
- html中第一行是什么意思
html中第一行是什么意思 一.总结 一句话总结: 告诉浏览器,让浏览器得知自己要处理的内容时html 二.html中第一行是什么意思 转自或参考:HTML文件第一行是什么东东_百度知道https:/ ...
- linux日常---3、linux常用操作
linux日常---3.linux常用操作 一.总结 一句话总结: 状态的确是非常之好,享受这种状态. 1.linux删除文件夹和文件? rm -rf *:删文件和文件夹 rm -rf *.*:只能删 ...