【凸包直径&平面最远点对&对锺点(旋转卡壳)】poj 2187 Beauty Contest
2015-10-01 21:38
555 查看
poj 2187 Beauty Contest
但是这是有局限性的 当凸包上的点达到O(N)的级别时 凸包的优化作用就不存在了
不过我们还要考虑到 凸包还起了对凸包上点集排序的作用
凸包有很多的优美的性质 我们可以加以利用 以得到更加高效的算法
加粗
斜体
引用
插入链接
插入代码
插入图片
提升标题
有序列表
无序列表
横线
撤销
重做
http://poj.org/problem?id=2187
问题描述:平面点集上最远点对&凸包直径&对锺点首先构造凸包,遍历所有点与点距离,取最大值。
这是利用了凸包上的点相比 点集中的点 一般是很少的 平均情况很好 并且我们也能AC这个问题但是这是有局限性的 当凸包上的点达到O(N)的级别时 凸包的优化作用就不存在了
不过我们还要考虑到 凸包还起了对凸包上点集排序的作用
凸包有很多的优美的性质 我们可以加以利用 以得到更加高效的算法
旋转卡壳算法就是利用凸包特性的一类解决问题的方法
http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html
思路
凸包构造+旋转卡壳 O(nlogn+n)参考代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<vector> #include<algorithm> #include<set> #include<sstream> #define eps 1e-9 #define pi acos(-1) using namespace std; typedef long long ll; const int _max = 5e4 + 10; int n; int dcmp(double x){ if(fabs(x)<eps) return 0;else return x < 0?-1:1; } struct point{ double x,y; }p[_max],res[_max]; bool mult(point sp,point ep,point op){ return (sp.x - op.x) * (ep.y - op.y) >= (ep.x - op.x) * (sp.y - op.y); } bool operator < (const point &l, const point &r){ return l.y < r.y ||(l.y == r.y && l.x < r.x); } int graham(point pnt[],int n, point res[]){//构造凸包 int i,len ,k = 0,top = 1; sort(pnt,pnt+n); if(n == 0)return 0; res[0] = pnt[0]; if(n == 1)return 1; res[1] = pnt[1]; if(n == 2)return 2; res[2] = pnt[2]; for(int i =2; i < n; ++ i){ while(top && mult(pnt[i],res[top],res[top-1])) top--; res[++top] = pnt[i]; } len = top; res[++top] = pnt[n - 2]; for(i = n - 3; i >= 0; -- i){ while(top!=len && mult(pnt[i],res[top],res[top-1])) top--; res[++top] = pnt[i]; } return top;//返回凸包中点的个数 } double len(point a,point b){//距离的平方 return (b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y); } double cross(point a,point b,point c){//(a,b)叉乘(a,c) return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y); } double rotating_caliper(){//凸包直径or平面最远点对(旋转卡壳) res = res [0]; double ans = 0; int q = 1; for(int p = 0; p < n; ++ p){ //卡出离边 res[i]-res[i+1]最远的点 while(cross(res[p+1],res[q+1],res[p])>cross(res[p+1],res[q],res[p])) q = (q+1)% n; ans = max(ans,max(len(res[p],res[q]),len(res[p+1],res[q+1]))); } return ans; } int main(){ #ifndef ONLINE_JUDGE freopen("input.txt","r",stdin); #endif // ONLINE_JUDGE while(scanf("%d",&n) == 1){ for(int i = 0; i < n; ++ i) scanf("%lf%lf",&p[i].x,&p[i].y); n = graham(p,n,res); double tar = rotating_caliper(); printf("%d\n",(int)tar); } return 0; }
加粗
Ctrl + B
斜体
Ctrl + I
引用
Ctrl + Q
插入链接
Ctrl + L
插入代码
Ctrl + K
插入图片
Ctrl + G
提升标题
Ctrl + H
有序列表
Ctrl + O
无序列表
Ctrl + U
横线
Ctrl + R
撤销
Ctrl + Z
重做
Ctrl + Y
相关文章推荐
- POJ 2187 Beauty Contest(凸包&&平面最远点对)
- NW.js的简单使用
- IntelliJ IDEA 优化总结
- find命令之xargs
- 批量修改AOT元素的属性 待续。。。
- 2015 Autumn Training #0
- 怎样不使用Useradd在linux下创建一个新的用户
- 达到XML简单的动态配置
- find命令之exec
- [C#]Windows系统特殊文件夹路径获取
- win7旗舰版(64位)环境下oracle11g的安装方法
- 惠普实训第一阶段总结,java项目总结,第二阶段计划
- find 命令概览
- openGL基础知识
- 当幸福来敲门
- uva 1635 唯一分解定理
- 【读后感】读《编程ING,人人都能学会程序设计》
- 【2015/10/1】Linux学习日志_Day3 管道 重定向 VIM 手动创建用户
- 第4章 IP协议
- 面向对象之继承和组合浅谈