您的位置:首页 > 其它

【凸包直径&平面最远点对&对锺点(旋转卡壳)】poj 2187 Beauty Contest

2015-10-01 21:38 555 查看
poj 2187 Beauty Contest

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息