您的位置:首页 > 其它

Poj 2187 Beauty Contest(旋转卡壳)

2012-12-20 11:57 417 查看
题目链接: http://poj.org/problem?id=2187
题意:给定平面上的一些散点集,求最远两点距离的平方值。

思路:Graham水平序。极角序判断共线很麻烦,可以参考这里http://blog.csdn.net/lyy289065406/article/details/6648617

虽然原题说 No two farms share the same pair of coordinates 但好像poj加入了重点。。。

参考了这里的代码http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html

这个题加深了我对凸包算法一些细节的理解。有时间再用Melkman做一下

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define max(x,y) ((x)>(y)?(x):(y))

const int NUM=50005;
struct Point
{
    int x,y;

	void get ()
	{
		scanf("%d%d",&x,&y);
    }
    bool operator < (const Point& _P) const
    {
        return y<_P.y||(y==_P.y&&x<_P.x);
    };
}pt[NUM],ch[NUM];
  
int cross (Point p,Point q,Point x)
{
	return (p.x-x.x)*(q.y-x.y)-(q.x-x.x)*(p.y-x.y);  
}

int dist2 (Point a,Point b)
{
	return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

void Graham (Point pt[],Point ch[],int &len,int n)
{
	int i,top=1;
    sort(pt,pt+n);
    ch[0]=pt[0];
    ch[1]=pt[1];
    for (i=2;i<n;i++)
    {
        while (top>0 && cross(ch[top],pt[i],ch[top-1]) <= 0)
            top--;
        ch[++top]=pt[i];
    }
    int temp=top;
    for (i=n-2;i>=0;i--)
    {
        while (top>temp && cross(ch[top],pt[i],ch[top-1]) <= 0)
            top--;
        ch[++top]=pt[i];
    }
    len=top;    
}

int Rotating_Calipers (Point ch[],int n)
{
	int q=1,ans=0;
	ch
=ch[0];
	for (int p=0;p<n;p++)
    {
        while (cross(ch[p+1],ch[q+1],ch[p]) > cross(ch[p+1],ch[q],ch[p]))
			q=(q+1)%n;
		ans=max(ans,max(dist2(ch[p],ch[q]),dist2(ch[p+1],ch[q+1])));
    }
    return ans;
}

int main ()
{
    int n,len;
    while (~scanf("%d",&n))
    {
        for (int i=0;i<n;i++)
            pt[i].get();
		Graham(pt,ch,len,n);
        printf("%d\n",Rotating_Calipers(ch,len));
    }
    return 0;
}

/*
4
0 0
1 0
2 0
-1 0

Out
9
*/
/*
10
4 3
0 0
0 3
0 2
2 2
3 3
3 0
3 4
3 1
5 5

Out
50
*/


贴一下大牛的快速凸包算法代码。速度没有Graham水平序快

//快速凸包算法(Quickhull Algorithm)

#include <iostream>
#include <cmath>
#define STD 1e-12
#define cmp(a,b) (a.x<b.x || DB(a.x-b.x)==0 && a.y<b.y)
using namespace std;

const int NUM=50005;

struct Point
{
    double x,y;
}p[NUM],ch[NUM];

double s[NUM];
int len=1,n;

int DB (double x)  
{  
    if (x>STD)  
        return 1;  
    if (x<-STD)  
        return -1;  
    return 0;  
} 

double cross (Point& o, Point& a, Point& b)   
{  
    return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);   
}

//ch[1]~ch[len]存储凸包
void Quickhull (int l,int r,Point a,Point b)
{
    int x=l,i=l-1,j=r+1,k;
    for (k=l;k<=r;k++)
	{
        double temp=DB(s[x]-s[k]);
        if (temp<0 || temp==0 && cmp(p[x],p[k])) x=k;//找距离最远点
    }
    Point y=p[x];
    for (k=l;k<=r;k++)
	{
        s[++i]=cross(p[k],a,y);
        if (DB(s[i])>0)           //划分点集
			swap(p[i],p[k]);
		else i--;
    }
    for (k=r;k>=l;k--)
	{
        s[--j]=cross(p[k],y,b);
        if (DB(s[j])>0)          //划分点集
			swap(p[j],p[k]);
		else j++;
    }
    if (l<=i)
		Quickhull(l,i,a,y);
    ch[++len]=y;
    if (j<=r)
		Quickhull(j,r,y,b);
}

double dis2 (Point a,Point b)
{
    return ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

int main ()
{
    int i,j,x=0;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
	{
        scanf("%lf%lf",&p[i].x,&p[i].y);
        if (x==0 || cmp(p[i],p[x]))
			x=i;
    }
    swap(p[1],p[x]);
    ch[1]=p[1];
    Quickhull (2,n,p[1],p[1]);
    double ans=0;
    for (i=1;i<=len;i++)
        for (j=i+1;j<=len;j++)
        {
            double tmp=dis2(ch[i],ch[j]);
            if (tmp > ans)
				ans=tmp;
        }
    printf("%.0lf\n",ans);
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: