hdu4454 Stealing a Cake

该博客探讨了一道题目,要求计算从特定点出发,经过一个圆,最终到达一个矩形的最短路径。通过枚举圆上的点并利用单峰函数性质,采用三分法寻找极值来解决此问题。
摘要由CSDN通过智能技术生成

题目大意给出一个点和一个圆和一个矩形,求一个点先到圆再到矩形的最短路径


可以枚举圆上的一点,然后求该点到矩形的最短距离。

圆上一点关于最短路在[0,Pi] and [pi,2*pi]两个区间上都是单峰函数,所以可以三分法求极值。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#define PI 3.1415926
using namespace std;
struct          Point
{
     double x,y;
     Point(double X,double Y)
     {
        x= X; y = Y;
     }
     Point operator-(const Point a)
     {
           return Point(x-a.x,y-a.y);
     }
     double operator^(const Point a)
     {
           return (x*a.y-y*a.x);
     }
     double operator*(const Point a)
     {
            return (x*a.x+y*a.y);
     }
};
double X,Y,R,X1,X2,Y1,Y2;
Point O(0,0);
double          Sqrt(double x){ return (x<1e-8?0:sqrt(x));}
double          Sqr(double x) { return x*x;}
double          dis(Point a, Point b)
{
     return (sqrt(Sqr(a.x-b.x)+Sqr(a.y-b.y)));
}
int   sign(double x)
{
      if (x>1e-8) return 1; else
      if (x<-1e-8) return -1;else
      return 0;
}
double          getDisLine(Point a,Point b,Point c)
{
     double ans = dis(a,b);
     ans = min(ans,dis(a,c));
     if (sign((c-b)*(a-b))>=0 &&  sign((b-c)*(a-c))>=0)
         ans = min(ans,fabs((c-a)^(b-a))/dis(c,b));
     return ans;
}
double          getDis(Point p)
{
     double len = dis(O,p);
     Point P1(X1,Y1);
     Point P2(X1,Y2);
     Point P3(X2,Y1);
     Point P4(X2,Y2);
     
     double d= getDisLine(p,P1,P2);
     d = min(d,getDisLine(p,P2,P4));
     d = min(d,getDisLine(p,P4,P3));
     d = min(d,getDisLine(p,P3,P1));
     return d+len;
}
double          Get(double l, double r)
{
     double ans = -1;
     while (r-l>=1e-8)
     {
           double mid1= l+(r-l)/3;
           double mid2= r-(r-l)/3;
           Point P1 = Point(X+R*cos(mid1),Y+R*sin(mid1));
           Point P2 = Point(X+R*cos(mid2),Y+R*sin(mid2));
     
           double len1 = getDis(P1);
           double len2 = getDis(P2);
           if (ans== -1 || ans>min(len1,len2)) ans = min(len1,len2);
           if (len1<len2) r= mid2; else l = mid1;
     }
     return ans;
}
int main()
{
    while (cin>>O.x>>O.y && !(O.x==0 && O.y==0))
    {
          cin>>X>>Y>>R;
          cin>>X1>>Y1>>X2>>Y2;
          double ans = Get(0,PI);
          ans = min(ans,Get(PI,2*PI));
          printf("%.2lf\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值