zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    poj 2411 Mondriaan's Dream 骨牌铺放 状压dp
    zoj 3471 Most Powerful (有向图)最大生成树 状压dp
    poj 2280 Islands and Bridges 哈密尔顿路 状压dp
    hdu 3001 Travelling 经过所有点(最多两次)的最短路径 三进制状压dp
    poj 3311 Hie with the Pie 经过所有点(可重)的最短路径 floyd + 状压dp
    poj 1185 炮兵阵地 状压dp
    poj 3254 Corn Fields 状压dp入门
    loj 6278 6279 数列分块入门 2 3
    VIM记事——大小写转换
    DKIM支持样本上传做检测的网站
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4276461.html
Copyright © 2011-2022 走看看