HDU 4454
想了很久,发现其实就只需要三分枚举圆上的点,到矩形的最短很容易就可以求到了。开始时考虑要不要根据矩形相对圆的方位来划分枚举区间,后来发现一定不能这样做的。
注意题目给的是矩形的对角形,但没说哪一条对角线哦,所以,注意。。。被这坑了好久。。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const double PI=3.141592653; const double eps=1e-8; const double inf=1e10; struct Point{ double x,y; }; double xmin,ymin,xmax,ymax,r; Point start,center,first; double ans; Point corn[4]; double cal(double ang){ double x=cos(ang)*first.x-sin(ang)*first.y; double y=cos(ang)*first.y+sin(ang)*first.x; double l1=sqrt((x-start.x)*(x-start.x)+(y-start.y)*(y-start.y)); double l2=inf; for(int i=0;i<4;i++){ l2=min(l2,sqrt((x-corn[i].x)*(x-corn[i].x)+(y-corn[i].y)*(y-corn[i].y))); } if(x-eps>=xmin&&x<=xmax-eps){ if(y<=ymin-eps){ l2=min(l2,ymin-y); } else if(y-eps>=ymax){ l2=min(l2,y-ymax); } } else if(y-eps>=ymin&&y<=ymax-eps){ if(x-eps>=xmax){ l2=min(l2,x-xmax); } else if(x<=xmin-eps){ l2=min(l2,xmin-x); } } return l1+l2; } int main(){ double l,r,m,mm; double a,b,c,d; while(scanf("%lf%lf",&start.x,&start.y)!=EOF){ if(fabs(start.x)<eps && fabs(start.y)<eps) break; scanf("%lf%lf%lf",¢er.x,¢er.y,&r); scanf("%lf%lf%lf%lf",&a,&b,&c,&d); xmin=min(a,c); xmax=max(a,c); ymin=min(b,d); ymax=max(b,d); start.x-=(center.x),start.y-=(center.y); xmin-=center.x,xmax-=center.x; ymin-=center.y,ymax-=center.y; center.x=center.y=0; corn[0].x=xmin,corn[0].y=ymin; corn[1].x=xmin,corn[1].y=ymax; corn[2].x=xmax,corn[2].y=ymin; corn[3].x=xmax,corn[3].y=ymax; first.x=center.x+r; first.y=center.y; l=0,r=PI; ans=inf; while(l+eps<r){ m=(r+l)/2; mm=(m+r)/2; if(cal(m)>cal(mm)){ l=m; } else r=mm; } ans=min(ans,cal(r)); l=-PI,r=0; while(l+eps<r){ m=(r+l)/2; mm=(m+r)/2; if(cal(m)>cal(mm)){ l=m; } else r=mm; } ans=min(ans,cal(r)); printf("%.2lf\n",ans); } return 0; }