Uvalive 4728 Squares(旋转卡壳)

来源:互联网 发布:mac grapher 编辑:程序博客网 时间:2024/05/19 13:21
题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2729

思路:

1.朴素算法可以枚举凸包上每条边,计算到这两条边两端点的距离最远点(与枚举点相同O(n^2))。

2.对于每一条边,凸包上点依次与其端点的距离成单峰函数(先增后减)。由此,逆时针选择边时,对应点的变化也是逆时针的(即可继续按上次枚举位置继续逆时针旋转)。

3.对应最远距离时,边与点组成的面积最大。由单调性,当点u、u+1、v+1组成的面积不再增加时(即Area(u,u+1,v+1)<Area(u,u+1,v)),对应的最长边也开始减小。此时应逆时针转动边,换下一条边枚举。

4.当Area(u,u+1,v+1)==Area(u,u+1,v)时(对应两线平行时),点u+1、v+1也可能组成最长边。

5. 当Area(p[u], p[u+1], p[v+1]) <= Area(p[u], p[u+1], p[v])时停止旋转:

    即Cross(p[u+1]-p[u], p[v+1]-p[u]) - Cross(p[u+1]-p[u], p[v]-p[u]) <= 0
    根据Cross(A,B) - Cross(A,C) = Cross(A,B-C)
    化简得Cross(p[u+1]-p[u], p[v+1]-p[v]) <= 0

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;const int maxn=4e5+50;const double eps=1e-6;struct Point{    double x,y;    Point(double x=0.0,double y=0.0):x(x),y(y) {}};typedef Point Vector;Point convex[maxn];Point p[maxn];int dcmp(double x){    if(fabs(x)<eps) return 0;    else return x<0?-1:1;}Vector operator - (Vector A,Vector B){    return Vector(A.x-B.x,A.y-B.y);}bool operator < (Vector A,Vector B){    if(A.x==B.x) return A.y<B.y;    else return A.x<B.x;}bool operator == (Vector A,Vector B){    return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0;}double Cross(Vector A,Vector B){    return A.x*B.y-A.y*B.x;}int ConvexHull(Point* p,int n,Point* ch){    int m=0;    sort(p,p+n);    n=unique(p,p+n)-p;    for(int i=0; i<n; i++)    {        while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;        ch[m++]=p[i];    }    int k=m;    for(int i=n-2; i>=0; i--)    {        while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;        ch[m++]=p[i];    }    if(n>1) m--;    return m;}int dist(Point A,Point B){    return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}int maxdist(Point* p,int n){    int ans=0;    p[n]=p[0];    for(int u=0,v=1; u<n; u++)    {        for(;;)        {            int tmp=Cross(p[u+1]-p[u],p[v+1]-p[v]);            if(tmp<=0)            {                ans=max(ans,dist(p[u],p[v]));                if(tmp==0) ans=max(ans,dist(p[u+1],p[v+1]));                break;            }            v=(v+1)%n;        }    }    return ans;}int main(){#ifdef debu    freopen("in.txt","r",stdin);#endif // debug    int t;    scanf("%d",&t);    while(t--)    {        int cnt=0,n;        scanf("%d",&n);        for(int i=0; i<n; i++)        {            int x,y,w;            scanf("%d%d%d",&x,&y,&w);            p[cnt++]=Point(x,y);            p[cnt++]=Point(x+w,y);            p[cnt++]=Point(x+w,y+w);            p[cnt++]=Point(x,y+w);        }        int num=ConvexHull(p,cnt,convex);        printf("%d\n",maxdist(convex,num));    }    return 0;}



原创粉丝点击