题目背景
此处省略1W字^ ^
题目描述
贝茜在牛的选美比赛中赢得了冠军”牛世界小姐”。因此,贝西会参观N(2 < = N < = 50000)个农场来传播善意。世界将被表示成一个二维平面,每个农场位于一对整数坐标(x,y),各有一个值范围在-10000…10000。没有两个农场共享相同的一对坐标。
尽管贝西沿直线前往下一个农场,但牧场之间的距离可能很大,所以她需要一个手提箱保证在每一段旅程中她有足够吃的食物。她想确定她可能需要旅行的最大可能距离,她要知道她必须带的手提箱的大小。帮助贝西计算农场的最大距离。
输入输出格式
输入格式:第一行:一个整数n
第2~n+1行:xi yi 表示n个农场中第i个的坐标
输出格式:一行:最远距离的[b]平方[/b]
输入输出样例
说明
NONE
题解:凸包模板+旋转卡壳模板。
旋转卡壳其实是个很傻逼的东西:
计算凸多边形上的最远点对(又叫直径)。这样考虑方法:对于每一个点,都求一求它到每个点的距离(这不就跟暴力没有区别了吗!!)。
这样做会有很多无用功。如果一根筷子边紧贴多边形的一条边,那么离这条边最远的点不就是与它们构成的最大面积的三角形吗?于是乎,每遍历一条边的时候,就把另外一个点朝相同方向转动直到面积最大(这个面积的变化是单峰的),然后求一求几个点的最短距离。(为什么是几个点?)因为另外一根筷子有可能与多边形的另外一条边重合。如下图:
旋转卡壳模板代码:
d[tot+1]=1;//tot为凸包定点个数 j=3; for(i=1;i<=tot;i++){ while(cha(a[d[i]],a[d[i+1]],a[d[j]])<cha(a[d[i]],a[d[i+1]],a[d[j+1]])){ j=(j+1)%tot; if(j==0)j=tot; } ans=max(ans,max(dis(a[d[i]],a[d[j]]),dis(a[d[i+1]],a[d[j]]))); } printf("%.0lf",ans);
非常傻逼。
下面上代码(要特判只有两个点):
#include<bits/stdc++.h> using namespace std; struct aaa{ double l,r; }a[100001]; int n,i,flag,tot,j,d[100001],l,r; double ans; double cha(aaa a,aaa b,aaa c){ return(b.l-a.l)*(c.r-a.r)-(c.l-a.l)*(b.r-a.r); } double dis(aaa a,aaa b){ return (b.l-a.l)*(b.l-a.l)+(b.r-a.r)*(b.r-a.r); } bool cmp(aaa aa,aaa b){ double t=cha(a[1],aa,b); return (t>0||(fabs(t)<1e-8&&dis(a[1],aa)<dis(a[1],b))); } int main(){ scanf("%d",&n); for(i=1;i<=n;i++)scanf("%lf%lf",&a[i].l,&a[i].r); if(n==2){ printf("%.0lf",dis(a[1],a[2])); return 0; } for(i=1;i<=n;i++){ if((!flag)||(a[i].l<l)||(a[i].l==l&&a[i].r<r)){ flag=i;l=a[i].l;r=a[i].r; } } a[0]=a[1]; a[1]=a[flag]; a[flag]=a[0]; sort(a+2,a+n+1,cmp); tot=3; d[1]=1;d[2]=2;d[3]=3; for(i=4;i<=n;i++){ while(tot>=2&&cha(a[d[tot-1]],a[d[tot]],a[i])<=0)tot--; d[++tot]=i; } d[tot+1]=1; j=3; for(i=1;i<=tot;i++){ while(cha(a[d[i]],a[d[i+1]],a[d[j]])<cha(a[d[i]],a[d[i+1]],a[d[j+1]])){ j=(j+1)%tot; if(j==0)j=tot; } ans=max(ans,max(dis(a[d[i]],a[d[j]]),dis(a[d[i+1]],a[d[j]]))); } printf("%.0lf",ans); }