您的位置:首页 > 其它

poj-2187-凸包-旋转卡壳法求直径

2014-01-06 13:33 411 查看
先求出凸包,时间复杂度O(n*log(n))

然后运用旋转卡壳发求出凸包的直径。

旋转卡壳法:

1.先求出y坐标最大的点为maxx,y最小的点为minn。

2.过minn,maxx点做一条平行于x轴的直线

3.俩直线分别对minn,maxx点逆时针旋转至某一条直线与凸包的某个点相交为止。

4,用交点更新前一个点。

5,重复3-4直至目前两点都出现过为止。

6,每次旋转之后得到的两点之间的距离的最大值即为凸包的直径

原理:

第一步寻找到的一对点(minn,maxx)一定是一对对踵点。

然后旋转直线会得到另外一对对踵点。

这样一直旋转就会得到所有的对踵点。

然后凸包的直径是某个对踵点直径的距离。

#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<iostream>
#include<stdio.h>
#include<vector>
#define INF 1000000
using namespace std;
struct list
{
    int x,y;
} node[50051],tu[50051];
int ts,n;
int vis[50051];
int len(struct list a,struct list b)
{
    int xx=a.x-b.x;
    int yy=a.y-b.y;
    return xx*xx+yy*yy;
}
int cmp1(struct list a,struct list b)
{
    if(a.y!=b.y)return a.y<b.y;
    return a.x<b.x;
}
int cmp2(struct list a,struct list b)
{
    int x1=a.x-node[1].x;
    int x2=b.x-node[1].x;
    int y1=a.y-node[1].y;
    int y2=b.y-node[1].y;
    if(x1*y2==x2*y1)return len(a,node[1])<len(b,node[1]);
    return x1*y2>x2*y1;
}
void push(int i)
{
    if(ts<=2)
    {
        tu[ts++]=node[i];
        return ;
    }
    int x1=tu[ts-1].x-tu[ts-2].x;
    int y1=tu[ts-1].y-tu[ts-2].y;
    int x2=node[i].x-tu[ts-1].x;
    int y2=node[i].y-tu[ts-1].y;
    if(x1*y2>x2*y1)tu[ts++]=node[i];
    else ts--,push(i);
}
void tubao()
{
    tu[0]=node[1];
    tu[1]=node[2];
    for(int i=3; i<=n; i++)push(i);
}
void diameter()
{
    int minn,maxx;
    minn=maxx=0;
    for(int i=0; i<ts; i++)
    {
        if(tu[minn].y>tu[i].y)minn=i;
        if(tu[maxx].y<tu[i].y)maxx=i;
    }
    int s1,s2;
    s1=minn;
    s2=maxx;
    int lens;
    lens=len(tu[s1],tu[s2]);
    memset(vis,0,sizeof(vis));
    while(vis[s1]==0||vis[s2]==0)
    {
        vis[s1]=vis[s2]=1;
        int x1=tu[s2].x-tu[(s2+1)%ts].x;
        int x2=tu[(s1+1)%ts].x-tu[s1].x;
        int y1=tu[s2].y-tu[(s2+1)%ts].y;
        int y2=tu[(s1+1)%ts].y-tu[s1].y;
        if(y1*x2<y2*x1)s2=(s2+1)%ts;//根据叉积判断旋转直线最先碰到哪条边
        else s1=(s1+1)%ts;
        lens=max(lens,len(tu[s1],tu[s2]));
    }
    cout<<lens<<endl;
}
int main()
{
    scanf("%d",&n);
    ts=2;
    for(int i=1; i<=n; i++)scanf("%d%d",&node[i].x,&node[i].y);
    sort(node+1,node+n+1,cmp1);
    sort(node+2,node+n+1,cmp2);
    tubao();
    diameter();
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: