hdu 4454 三分+幾何
阿新 • • 發佈:2018-12-24
題目大意:給一個點,一個圓和一個矩形,矩形與圓沒有重疊部分,點也在圓和矩形外,求從該點出發經過圓上一點再到矩形邊上一點的距離和的最小值。
思路:三分角度求最小距離和。
#include<iostream> #include<cstdio> #include<cstdlib> #include<vector> #include<cmath> #include<string> #include<algorithm> #include<set> #include<map> #include<cstring> #include<queue> #include<stack> #include<list> using namespace std; typedef long long ll; const int maxn=1000+5; const int inf=1e9; const ll mod=1e9+7; const double pi=acos(-1.0); struct point{ double x,y; point(){} point (double _x,double _y){ x=_x;y=_y; } point operator-(const point &ne)const{ return point (x-ne.x,y-ne.y); } point operator+(const point &ne)const{ return point (x+ne.x,y+ne.y); } point operator*(const double t)const{ return point (x*t,y*t); } }; struct line{ point a,b; line (){} line(point _a,point _b){a=_a;b=_b;} }; struct circle{ point O; double r; }; double dmult(point a,point b){ return a.x*b.x+a.y*b.y; } inline double lenth(point a){ return sqrt(dmult(a,a)); } inline double dist(point a,point b){ return lenth(b-a); } inline double dist2(point a,point b){ return dmult(b-a,b-a); } double relation(point p,line l){ line t1(l.a,p); return dmult(t1.b-l.a,l.b-l.a)/dist2(l.a,l.b); } point perpend(point p,line l){ double r=relation (p,l); return l.a+((l.b-l.a)*r); } double distoline(point p,line l){ double r=relation(p,l); if(r<0){ return dist(p,l.a); } if(r>1)return dist(p,l.b); point np=perpend(p,l); return dist(p,np); } const double eps=1e-9; double sx,sy; double x,y,r; circle cir; point start; point P[4]; line L[4]; double cal(double alpha){ double x,y; x=cir.O.x+cir.r*cos(alpha); y=cir.O.y+cir.r*sin(alpha); double res=1e18; point pp=point(x,y); double tmp=dist(pp,start); for(int i=0;i<4;i++){ res=min(res,distoline(pp,L[i])); } return res+tmp; } double Solve(double leftvale,double rightvale) { //三分{ double Left, Right; double mid, midmid; double mid_value, midmid_value; Left = leftvale; Right = rightvale; while (Left + eps< Right) { //mid = (Left + Right) / 2; mid=Left+(Right-Left)/3; midmid = Right-(Right-Left)/3; mid_value = cal(mid); midmid_value = cal(midmid); // 假設求解最xiao極值. if (mid_value < midmid_value) Right = midmid; else Left = mid; } return cal(Left); } int main() { while(scanf("%lf%lf",&sx,&sy)!=EOF){ if(sx==0&&sy==0)break; start.x=sx;start.y=sy; scanf("%lf%lf%lf",&x,&y,&r); cir.O.x=x;cir.O.y=y;cir.r=r; double X1,Y1,X2,Y2; scanf("%lf%lf%lf%lf",&X1,&Y1,&X2,&Y2); P[0].x=X1;P[0].y=Y1; P[1].x=X1;P[1].y=Y2; P[2].x=X2;P[2].y=Y2; P[3].x=X2;P[3].y=Y1; L[0]=line(P[0],P[1]); L[1]=line(P[1],P[2]); L[2]=line(P[2],P[3]); L[3]=line(P[3],P[0]); double ans=min(Solve(0,pi),Solve(pi,2*pi)); printf("%.2f\n",ans); } return 0; }