Uvalive 4728 Squares(旋转卡壳)
2017-08-22 19:38
381 查看
题目地址: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
思路:
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 =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; }
相关文章推荐
- UVALive 4728 Squares(旋转卡壳)
- UVALive 4728 Squares(旋转卡壳求凸包直径)
- UVA 4728 Squares(凸包+旋转卡壳)
- 凸包扫描 + 旋转卡壳 UVALive 4728
- UVALive 4728 (凸包 旋转卡壳)
- uvalive 4728(旋转卡壳求凸包最长直径)
- UVa 1453 - Squares 旋转卡壳求凸包直径
- UVALive 4728 Squares
- Squares UVALive - 4728
- LA 4728 (旋转卡壳) Squares
- LA 4728 Squares 旋转卡壳
- uva 1453 - Squares(旋转卡壳)
- UVALive 4728 Squares (平面最远点对)
- LA 4728 Squares (二维凸包+旋转卡壳)
- uva 1453 Squares (旋转卡壳 rotating calipers)
- UVA 10173 最小矩形覆盖(凸包+旋转卡壳)
- UVA 10173 Smallest Bounding Rectangle (旋转卡壳最小面积外接矩形)
- UVA 10173 最小矩形覆盖(凸包+旋转卡壳)
- UVALive_6602_Counting Lattice Squares(公式推导)
- 【最小矩形面积覆盖:凸包+旋转卡壳】UVA 10173 Smallest Bounding Rectangle