题意:给你平面上一些点,求一个凸包的最短直径
思路:旋转卡壳,然后搞一下就行了可旋转卡壳求最远点差不多,cur带表的是求出的对锺点,然后与当前的直线p[i],p[i+1],求一下距离
代码:
#include <bits/stdc++.h> using namespace std; const double eps = 1e-16; int sgn(double x) { if(fabs(x) < eps)return 0; if(x < 0)return -1; else return 1; } struct point { double 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); } double operator ^(const point &b)const { return x*b.y - y*b.x; } double operator *(const point &b)const { return x*b.x + y*b.y; } void sc() { scanf("%lf%lf",&x,&y); } }; struct Line { point s,e; Line() {} Line(point _s,point _e) { s = _s; e = _e; } pair<int,point> operator &(const Line &b)const { point res = s; if(sgn((s-e)^(b.s-b.e)) == 0) { if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res); else return make_pair(1,res); } double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x += (e.x-s.x)*t; res.y += (e.y-s.y)*t; return make_pair(2,res); } }; double dist(point a,point b) { return (double)sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } point NearestpointToLineSeg(point P,Line L) { point result; double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s)); if(t >= 0.000 && t <= 1.0000) { result.x = L.s.x + (L.e.x - L.s.x)*t; result.y = L.s.y + (L.e.y - L.s.y)*t; } else { if(dist(P,L.s) < dist(P,L.e)) result = L.s; else result = L.e; } return result; } double emmm(point P,Line L) { point zz=NearestpointToLineSeg(P,L); return dist(zz,P); } const int MAXN = 2e5+7; point List[MAXN]; int Stack[MAXN],top; bool _cmp(point p1,point p2) { double tmp = (p1-List[0])^(p2-List[0]); if(tmp > 0)return true; else if(tmp == 0 && dist(p1,List[0]) <= dist(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[k],List[0]); 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 && ((List[Stack[top-1]]-List[Stack[top-2]])^(List[i]-List[Stack[top-2]])) <= 0) top--; Stack[top++] = i; } } double rotating_calipers(point p[],int n) { double ans = 999999999999999999999.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;s } Line qw=Line(p[(i)%n],p[(i+1)%n]); // point zz=NearestpointToLineSeg(p[cur],qw); double as=emmm(p[cur],qw); //as=max(as,zx); ans=min(ans,as); // ans=min(ans,max(dist(p[i],p[cur]),dist(p[(i+1)%n],p[(cur+1)%n]))); } return ans; } point p[MAXN]; int main() { int n,r; while(~scanf("%d%d",&n,&r)) { for(int i = 0; i < n; i++)List[i].sc(); Graham(n); for(int i = 0; i < top; i++)p[i] = List[Stack[i]]; printf("%.16f\n",rotating_calipers(p,top)); } return 0; }
原文地址:https://www.cnblogs.com/lalalatianlalu/p/8973980.html
时间: 2024-10-15 04:23:06