UVA, 10180 Rope Crisis in Ropeland!

题意:求两点之间的最短距离,如果两点穿过圆,则距离是两条切线加一段弧长,图上有。

分析: 用三角形的余弦定理和正弦定理,可以求出相应的一些角度,其实这道题就是一个简单的几何问题,几何会做这道题就会了。






#include <iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<list>
#include<cstring>
using namespace std;
#define EPS 1e-8
#define N 1005
int ans[N];
struct point
{
    double a,b;
    point(){}
    point(double a,double b):a(a),b(b){}
    point operator +(point p)
    {
        return point(p.a+a,p.b+b);
    }
    point operator -(point p)
    {
        return point(a-p.a,b-p.b);
    }
    point operator *(double p)
    {
        return point(a*p,b*p);
    }
    double dot(point p)//内积
    {
        return (p.a*a+p.b*b);
    }
    double det(point p)//外积
    {
        return (a*p.b-b*p.a);
    }
};
struct seg
{
    int index;
    point p1,p2;
};
point p1,p2;
vector<seg>v;
//判断q是否在线段p1-p2上
bool on_str(point p1,point p2,point q)
{
    return (abs((p1-q).det(p2-q))<EPS&&(p1-q).dot(p2-q)<EPS);
}
//求两直线交点
point intersection(point p1,point p2,point q1,point q2)
{
    return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
//两点之间的距离
double dist(point p1,point p2)
{
    return sqrt((p1.a-p2.a)*(p1.a-p2.a)+(p1.b-p2.b)*(p1.b-p2.b));
}
//点到直线的距离
double p_seg_dis(point p,point p1,point p2)
{
    // A = y1 - y2;
 //B = x2 - x1;
 //C = x1 * y2 - x2 * y1;
    point p3((p1.b-p2.b),(p2.a-p1.a));
//   D = fabs(A * x3 + B * y3 + C) / sqrt(A * A + B * B);
   // ((p1.b-p2.b)*p.a+(p2.a-p1.a)*p.a)/dis(point())
  //   cout<<(p.dot(p3)+p1.det(p2))/dist(point(0,0),p3)<<endl;
    return fabs((p.dot(p3)+p1.det(p2))/dist(point(0,0),p3));
}
int main()
{
     int n;
     scanf("%d",&n);
     point p1,p2,p(0,0);
     while(n--)
     {
         double r;
         scanf("%lf%lf%lf%lf%lf",&p1.a,&p1.b,&p2.a,&p2.b,&r);
         if(p_seg_dis(p,p1,p2)>r)
         {
             printf("%.3f\n",dist(p1,p2));
         }
         else
         {
             double ans;
             double a=dist(p1,p);
             double b=dist(p2,p);
             double c=dist(p1,p2);
            if((a*a+c*c-b*b)<=0||(b*b+c*c-a*a)<=0)
            {
                printf("%.3f\n",dist(p1,p2));
                continue;
            }
             ans=sqrt(a*a-r*r)+sqrt(b*b-r*r);
             double angle=acos((a*a+b*b-c*c)/(2*a*b))-acos(r/a)-acos(r/b);
             ans+=angle*r;
             printf("%.3f\n",ans);
         }
     }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值