1. 程式人生 > >Gym 101606B - Breaking Biscuits - [凸包+旋轉卡殼][凸包的寬度]

Gym 101606B - Breaking Biscuits - [凸包+旋轉卡殼][凸包的寬度]

diameter ble cross The ati href str bool b-

題目鏈接:https://codeforces.com/gym/101606/problem/B

題解:

對於給出的 $n$ 個點,先求這些點的凸包,然後用旋轉卡殼求出凸包的寬度(Width (minimum width) of a convex polygon)即可。

旋轉卡殼求凸包的寬度和求凸包的直徑(Diameter (maximum width) of a convex polygon)差不多。

AC代碼:

#include<bits/stdc++.h>
#define mk make_pair
#define fi first
#define se second
#define
pb push_back using namespace std; const double eps=1e-8; const double INF=1e18; int Sign(double x) { if(x<-eps) return -1; if(x>eps) return 1; return 0; } int Cmp(double x,double y){return Sign(x-y);} struct Point { double x,y; Point(double _x=0,double _y=0):x(_x),y(_y){} Point
operator+(const Point &o)const{return Point(x+o.x,y+o.y);} Point operator-(const Point &o)const{return Point(x-o.x,y-o.y);} Point operator*(double k)const{return Point(x*k,y*k);} Point operator/(double k)const{return Point(x/k,y/k);} int operator==(const Point &o)const{return
Cmp(x,o.x)==0 && Cmp(y,o.y)==0;} bool operator<(const Point &o)const { int sgn=Cmp(x,o.x); if(sgn==-1) return 1; else if(sgn==1) return 0; else return Cmp(y,o.y)==-1; } void print(){printf("%.11f %.11f\n",x,y);} }; typedef Point Vctor; //叉積 double Cross(Vctor A,Vctor B){return A.x*B.y-A.y*B.x;} double Cross(Point O,Point A,Point B){return Cross(A-O,B-O);} //距離 double Dot(Vctor A,Vctor B){return A.x*B.x+A.y*B.y;} double Length(Vctor A){return sqrt(Dot(A,A));} double Length(Point A,Point B){return Length(A-B);} vector<Point> ConvexHull(vector<Point> P,int flag=1) //flag=0不嚴格 flag=1嚴格 { if(P.size()<=1) return P; int sz=P.size(); vector<Point> ans(2*sz); sort(P.begin(),P.end()); int now=-1; for(int i=0;i<sz;i++) { while(now>0 && Sign(Cross(ans[now]-ans[now-1],P[i]-ans[now-1]))<flag) now--; ans[++now]=P[i]; } int pre=now; for(int i=sz-2;i>=0;i--) { while(now>pre && Sign(Cross(ans[now]-ans[now-1],P[i]-ans[now-1]))<flag) now--; ans[++now]=P[i]; } ans.resize(now); return ans; } double RotatingCalipers(const vector<Point> &P) //旋轉卡殼法 { double ans=INF; int sz=P.size(); for(int i=0,q=1;i<sz;i++) { int j=(i+1)%sz; while( Cross(P[j]-P[i],P[q]-P[i]) < Cross(P[j]-P[i],P[(q+1)%sz]-P[i]) ) q=(q+1)%sz; double d=fabs(Cross(P[i],P[j],P[q]))/Length(P[i],P[j]); ans=min(ans,d); } return ans; } int n; vector<Point> P; int main() { cin>>n; for(int i=1;i<=n;i++) { double x,y; cin>>x>>y; P.pb(Point(x,y)); } double ans=RotatingCalipers(ConvexHull(P)); printf("%.8f\n",ans); }

Gym 101606B - Breaking Biscuits - [凸包+旋轉卡殼][凸包的寬度]