凸包+旋转卡壳模板——kuangbin版

凸包没什么好说的,旋转卡壳就是在一个先增再减的距离中找到极值,个人觉得还可以用三分找这个极值点,但也是仅仅加快了第一遍的速度,完全没必要。。。

胡言乱语。。。

这个速度明显不慢,三分根本没必要。

 

 

#include <stdio.h>
#include <string.h>
#include <algorithm> #include <iostream> using namespace std; struct Point { int x,y; Point(int _x = 0, int _y = 0) { x = _x; y = _y; } Point operator -(const Point &b)const { return Point(x - b.x, y - b.y); } int operator ^(const Point &b)const { return x*b.y - y*b.x; } int operator *(const Point &b)const { return x*b.x + y*b.y; } void input() { scanf("%d%d",&x,&y); } }; int dist2(Point a,Point b) { return (a-b)*(a-b); } int cross(Point p0,Point p1,Point p2) //计算叉积 p0p1 X p0p2 { return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); } const int MAXN = 50010; Point list[MAXN]; int Stack[MAXN],top; bool _cmp(Point p1,Point p2) { int tmp = cross(p1,p2,list[0]); if(tmp > 0)return true; else if(tmp == 0 && dist2(p1,list[0]) <= dist2(p2,list[0])) return true; else return false; } void Graham(int n) { Point p0; int k = 0; p0 = list[0]; for(int i = 1;i < n;i++) if(p0.y > list[i].y || (p0.y == list[i].y && p0.x > list[i].x)) { p0 = list[i]; k = i; } swap(list[0],list[k]); sort(list+1,list+n,_cmp); if(n == 1) { top = 1; Stack[0] = 0; return; } if(n == 2) { top = 2; Stack[0] = 0; Stack[1] = 1; return; } Stack[0] = 0; Stack[1] = 1; top = 2; for(int i = 2;i < n;i++) { while(top > 1 && (cross(list[Stack[top-1]],list[i],list[Stack[top-2]])) <= 0 ) top--; Stack[top++] = i; } } //旋转卡壳,求两点间距离平方的最大值 int rotating_calipers(Point p[],int n) { int ans = 0; Point v; int cur = 1; for(int i = 0;i < n;i++) { v = p[i]-p[(i+1)%n]; while((v^(p[(cur+1)%n]-p[cur])) < 0) cur = (cur+1)%n; //printf("%d %d\n",i,cur); ans = max(ans,max(dist2(p[i],p[cur]),dist2(p[(i+1)%n],p[(cur+1)%n]))); } return ans; } Point p[MAXN]; int main() { int n; while(scanf("%d",&n) == 1) { for(int i = 0;i < n;i++) list[i].input(); Graham(n); for(int i = 0;i < top;i++) p[i] = list[Stack[i]]; printf("%d\n",rotating_calipers(p,top)); } return 0; }

转载于:https://www.cnblogs.com/nj-czy/p/5314718.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值