題目連接c++
題意:給出第一象限的N個點,存在一直線x/a+y/b=1(a>0,y>0)使得全部點都在這條直線下面,求 min{sqrt(a^2+b^2)}函數
顯然,這樣的直線必然通過這N個點中的某一個(可用反證法證得),因此先對只有一個點的狀況進行分析。spa
當只有一個點P(x0,y0)時,易得.net
此時設t=a/b,可知,a^2+b^2可寫成兩個凹函數相加的形式,故可用三分法求解。code
因此N個點的狀況就可解了。容易想到,只須要考慮凸包上位於右上側的點(知足該點的左上方右下方都有點),那麼該點就有成爲「關鍵的點」的可能,至於三分時的自變量的範圍,就根據這個點的先後兩個點來獲得便可。blog
#include<bits/stdc++.h> using namespace std; const double eps=1e-9; const double inf=2e6; int dcmp(double x) { if(fabs(x)<eps) return 0; else return x<0? -1:1; } struct Point { double x,y; Point(double x_=0,double y_=0) { x=x_,y=y_; } Point operator -(const Point& rhs) { return Point(x-rhs.x,y-rhs.y); } bool operator<(const Point& rhs)const { return x<rhs.x||x==rhs.x&&y<rhs.y; } }; typedef Point Vector; double Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; } double Area2(Point A,Point B,Point C) { return Cross(B-A,C-A); } int ConvexHull(Point *p,int n,Point *ch) { sort(p,p+n); int m=0; for(int i=0; i<n; i++) { while(m>1&&dcmp(Area2(ch[m-2],ch[m-1],p[i]))<=0) --m; ch[m++]=p[i]; } int k=m; for(int i=n-2; i>=0; --i) { while(m>k&&dcmp(Area2(ch[m-2],ch[m-1],p[i]))<=0) --m; ch[m++]=p[i]; } return n>1? m-1:m; } //============================================================= const int maxn=1e6+5; Point p[maxn],ch[maxn]; double k[maxn]; double xielv(Point A,Point B) { if(dcmp(A.x-B.x)==0) return -inf; else return (A.y-B.y)/(A.x-B.x); } double cal(Point P,double P_k) { double a=P.x-P.y/P_k; double b=P.y-P.x*P_k; return sqrt(a*a+b*b); } double sanfen(Point P,double k1,double k2) { double l=k1,r=k2; while(r-l>eps) { double mid=(l+r)/2; double f1=cal(P,mid); double midmid=(mid+r)/2; double f2=cal(P,midmid); if(f1<f2) r=midmid; else l=mid; } return cal(P,l); } int main() { int n,m; while(~scanf("%d",&n)) { double ans=inf; double maxx=0,maxy=0; for(int i=0; i<n; i++) //讀點 { scanf("%lf%lf",&p[i].x,&p[i].y); maxx=max(maxx,p[i].x),maxy=max(maxy,p[i].y); } p[n++]=Point(maxx,0),p[n++]=Point(0,maxy); //加點,便於處理 m=ConvexHull(p,n,ch); //求凸包 for(int i=0; i<m; i++) k[i]=xielv(ch[i],ch[(i+1)%m]); //求斜率 for(int i=0; i<m; i++) if(ch[i].x>=ch[(i+1)%m].x&&ch[i].y<=ch[(i+1)%m].y && ch[(i+1)%m].x>=ch[(i+2)%m].x&&ch[(i+1)%m].y<=ch[(i+2)%m].y) ans=min(ans,sanfen(ch[(i+1)%m],k[i],k[(i+1)%m])); printf("%.3lf\n",ans+eps); } }