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",&center.x,&center.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;
}

  

posted @ 2015-02-06 10:02  chenjunjie1994  阅读(212)  评论(0编辑  收藏  举报