zoukankan      html  css  js  c++  java
  • HDU 4454

    我比较快速的想到了三分,但是我是从0到2*pi区间进行三分,并且漏了一种点到边距离的情况,一直WA了好几次

    后来画了下图才发现,0到2*pi区间内是有两个极值的,每个半圆存在一个极值

    以下是代码

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #define pi acos(-1.0)
    using namespace std;
    
    typedef struct
    {
        double x;
        double y;
    }point;
    
    typedef struct
    {
        double x;
        double y;
        double r;
    }circle;
    
    typedef struct
    {
        point s;
        point e;
    }line;
    
    
    double dis(point a,point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    double cal(point st,line ed,circle c,double t)
    {
        point p;
        p.x=c.x+cos(t)*c.r;
        p.y=c.y+sin(t)*c.r;
        if(fabs(ed.s.x-ed.e.x)<1e-8)
        {
            if(p.y>ed.s.y&&p.y<ed.e.y)
            {
                return dis(p,st)+fabs(p.x-ed.s.x);
            }
            else
            {
                double t=min(dis(p,ed.s),dis(p,ed.e));
                return dis(p,st)+t;
            }
    
        }
        if(fabs(ed.s.y-ed.e.y)<1e-8)
        {
            if(p.x>ed.s.x&&p.x<ed.e.x)
            {
                return dis(p,st)+fabs(p.y-ed.s.y);
            }
            else
            {
                double t=min(dis(p,ed.s),dis(p,ed.e));
                return dis(p,st)+t;
            }
        }
        return -1;
    }
    
    double solve1(point st,line ed,circle c)
    {
        double L=0,R=pi,mid=(L+R)/2,midmid=(mid+R)/2;
        while(R-L>1e-10)
        {
            if(cal(st,ed,c,mid)<cal(st,ed,c,midmid))R=midmid;
            else L=mid;
            mid=(L+R)/2;
            midmid=(R+mid)/2;
        }
        return cal(st,ed,c,midmid);
    }
    
    double solve2(point st,line ed,circle c)
    {
        double L=pi,R=2*pi,mid=(L+R)/2,midmid=(mid+R)/2;
        while(R-L>1e-10)
        {
            if(cal(st,ed,c,mid)<cal(st,ed,c,midmid))R=midmid;
            else L=mid;
            mid=(L+R)/2;
            midmid=(R+mid)/2;
        }
        return cal(st,ed,c,midmid);
    }
    
    int main()
    {
        double m,x[2],y[2];
        point st;
        circle cir;
        line a[4];
        while(scanf("%lf%lf",&st.x,&st.y)==2)
        {
            if(!st.x&&!st.y)break;
            scanf("%lf%lf%lf",&cir.x,&cir.y,&cir.r);
            scanf("%lf%lf",&x[0],&y[0]);
            scanf("%lf%lf",&x[1],&y[1]);
            if(x[0]>x[1]) swap(x[0],x[1]);
            if(y[0]>y[1]) swap(y[0],y[1]);
            a[0].s.x=x[0];a[0].s.y=y[0];
            a[0].e.x=x[0];a[0].e.y=y[1];
            a[1].s.x=x[0];a[1].s.y=y[0];
            a[1].e.x=x[1];a[1].e.y=y[0];
            a[2].s.x=x[1];a[2].s.y=y[0];
            a[2].e.x=x[1];a[2].e.y=y[1];
            a[3].s.x=x[0];a[3].s.y=y[1];
            a[3].e.x=x[1];a[3].e.y=y[1];
            m=1e18;
            for(int i=0;i<4;i++)
            {
                double t=solve1(st,a[i],cir);
                if(t<m)m=t;
                t=solve2(st,a[i],cir);
                if(t<m)m=t;
            }
            printf("%.2lf
    ",m);
        }
        return 0;
    }
    


  • 相关阅读:
    [Windows内核分析]KPCR结构体介绍 (CPU控制区 Processor Control Region)
    利用C++实现模块隐藏(R3层断链)
    [动态规划]最少硬币问题
    [动态规划]高数Umaru系列(9)——哈士奇(背包问题)
    Windows中利用共享内存来实现不同进程间的通信
    [分治算法]骨牌铺方格
    [分治、递推法、动态规划]最大子段和
    [分治算法]因式分解
    013 CephFS文件系统
    012 Ceph多区域网关
  • 原文地址:https://www.cnblogs.com/riskyer/p/3297356.html
Copyright © 2011-2022 走看看