Uvalive 4728 Squares(旋转卡壳)

62 篇文章 0 订阅
7 篇文章 0 订阅
题目地址: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 debug
using 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;
}



### 回答1: `squares.append()`是Python语言中列表对象的一个方法,用于在列表末尾添加一个元素。例如,如果你有一个名为"squares"的列表,并且想在其末尾添加数字9,你可以使用以下代码: ``` squares.append(9) ``` 这将在列表末尾添加数字9。 ### 回答2: 在Python中,squares.append()是一个列表方法,用于向列表中添加元素。该方法接受一个参数,即要添加的元素,并将该元素添加到列表的末尾。 例如,假设我们有一个空列表squares。我们可以使用以下代码将一个元素添加到列表中: squares = [] squares.append(4) 现在,squares列表将包含一个元素,即数字4。我们可以进一步使用append()方法来添加更多的元素到列表中。例如: squares.append(9) squares.append(16) squares.append(25) 现在,squares列表将依次包含数字4、9、16和25。 总结而言,squares.append()是一个有用的列表方法,它允许我们在Python中向列表中添加元素。无论列表是否为空,我们都可以使用append()方法将元素添加到列表的末尾。 ### 回答3: `python squares.append`是Python语言中的一个方法,用于将一个元素追加到列表(list)中。在使用该方法时,需要先创建一个列表对象,并且可以在括号内指定要追加的元素。 例如,以下是一个使用`squares.append`的示例: ```python squares = [] # 创建一个空的列表对象 # 使用append方法将元素依次追加到列表中 squares.append(1) squares.append(4) squares.append(9) squares.append(16) print(squares) # 输出结果为:[1, 4, 9, 16] ``` 在上述示例中,我们首先创建了一个空的列表对象`squares`。然后,使用`squares.append`方法依次向列表中追加了四个元素,分别是1、4、9和16。最后,通过`print(squares)`将列表内容打印输出,结果为`[1, 4, 9, 16]`。 总而言之,`python squares.append`是用于将一个元素追加到列表中的Python方法,可以方便地扩充列表的内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值