csuoj 1503: 点到圆弧的距离

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503

1503: 点到圆弧的距离

时间限制: 1 Sec  内存限制: 128 MB  Special Judge 提交: 247  解决: 59 [提交][状态][讨论版]

题目描述

输入一个点P和一条圆弧(圆周的一部分),你的任务是计算P到圆弧的最短距离。换句话说,你需要在圆弧上找一个点,到P点的距离最小。 提示:请尽量使用精确算法。相比之下,近似算法更难通过本题的数据。

输入

输入包含最多10000组数据。每组数据包含8个整数x1, y1, x2, y2, x3, y3, xp, yp。圆弧的起点是A(x1,y1),经过点B(x2,y2),结束位置是C(x3,y3)。点P的位置是 (xp,yp)。输入保证A, B, C各不相同且不会共线。上述所有点的坐标绝对值不超过20。

输出

对于每组数据,输出测试点编号和P到圆弧的距离,保留三位小数。你的输出和标准输出之间最多能有0.001的误差。

样例输入

0 0 1 1 2 0 1 -1
3 4 0 5 -3 4 0 1

样例输出

Case 1: 1.414
Case 2: 4.000

提示

来源

湖南省第十届大学生计算机程序设计竞赛

分析:

分两种情况就可以了,第一种是那个点跟圆心的连线在那段扇形的圆弧范围内,这样的话点到圆弧的最短距离就是点到圆心的距离减去半径然后再取绝对值就可以了,第二种情况是那个点跟圆心的连线不在那段扇形的圆弧范围内,这样的话,最短的距离就是到这段圆弧的端点的最小值。

接下来的第一步就是求圆心的坐标跟圆的半径,只要求出圆心坐标半径就好说了,求圆心坐标我用的方法是:

设圆心坐标是(a,b),然后列方程:

(x1-a)^2 + (y1-b)^2 = r^2;

(x2-a)^2 + (y2-b)^2 = r^2;

(x3-a)^2 + (y3-b)^2 = r^2;

然后这样的话,计算过程中会出现y2-y1做分母的情况,所以,我又分了两种情况来讨论。

求出圆心坐标然后接下来的问题就只有怎么判断那个点跟圆心的连线是不是在扇形的圆弧范围内了,我也是用了分情况讨论的,但这里分的情况还是比较多的,一开始分了8种情况,然后压缩了一下,变成4种情况,分别是:

判断给点的顺序是顺时针还是逆时针,然后判断区间的方向,然后就是判断那个点是不是跟p2点在同一个区间就可以了。

AC代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 const double eps = 1e-6,PI = acos(-1.0);
  8
  9 struct Point
 10 {
 11     double x,y;
 12     friend Point operator - (Point a,Point b)
 13     {
 14         Point temp;
 15         temp.x = a.x - b.x;
 16         temp.y = a.y - b.y;
 17         return temp;
 18     }
 19 };
 20
 21 Point p1,p2,p3,pc,pp;
 22 double r;
 23
 24 Point get_pc1(Point p1, Point p2, Point p3)    //求圆心
 25 {
 26   Point p;
 27   if(fabs(p1.y-p2.y) > eps)      //因为计算过程中有出现(y2-y1)做分母的情况,所以这里分了两种情况讨论
 28   {
 29  //      double t1 = p3.x*p3.x - p1.x*p1.x+p3.y*p3.y-p1.y*p1.y-((p3.y-p1.y)*(p1.x*p1.x-p2.x*p2.x+p1.y*p1.y-p2.y*p2.y)) / (p2.y-p1.y);
 30    //    double t2 = 2.0*(p3.x-p1.x)-(2*(p3.y-p1.y)*(p2.x-p1.x)) / (p2.y-p1.y);
 31         double  t1 = (p2.x*p2.x-p1.x*p1.x+p2.y*p2.y-p1.y*p1.y) *(p3.y-p1.y) - (p2.y-p1.y)*(p3.x*p3.x-p1.x*p1.x+p3.y*p3.y-p1.y*p1.y);
 32         double t2 = 2.0*((p3.y-p1.y)*(p2.x-p1.x) - (p2.y-p1.y)*(p3.x-p1.x));
 33        p.x = t1 / t2;
 34        p.y = (p2.x*p2.x-p1.x*p1.x+p2.y*p2.y-p1.y*p1.y-2*(p2.x-p1.x)*p.x) / (2*(p2.y-p1.y));
 35     }
 36     else
 37     {
 38         p.x = (p2.x*p2.x-p1.x*p1.x+p2.y*p2.y-p1.y*p1.y) / (2*(p2.x-p1.x));
 39         p.y = (p3.x*p3.x-p1.x*p1.x+p3.y*p3.y-p1.y*p1.y-2*(p3.x-p1.x)*p.x) / (2*(p3.y-p1.y));
 40     }
 41     return p;
 42 }
 43 double dis(Point a,Point b)
 44 {
 45     return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
 46 }
 47 double mult_ca(Point p1,Point p2)   //叉乘
 48 {
 49     return p1.x * p2.y - p2.x * p1.y;
 50 }
 51
 52 double get_ans(Point pc,Point pp,Point p1,Point p2,Point p3)
 53 {
 54     double temp = mult_ca(p2-p1,p3-p1);
 55     double f1 = atan2((p1-pc).x,(p1-pc).y);
 56     double f2 = atan2((p3-pc).x,(p3-pc).y);
 57     double f3 = atan2((p2-pc).x,(p2-pc).y);
 58     double f4 = atan2((pp-pc).x,(pp-pc).y);
 59     double ans1 = fabs(dis(pp,pc)-dis(p1,pc));
 60     double ans2 = min(dis(pp,p1),dis(pp,p3));
 61     if(temp < 0)    //顺时针给点
 62     {
 63         if(f1 < f2)      //判断区间方向,这样有利于判断p点和p2点是不是在同一个区间
 64         {
 65             if((f3 >= f1 && f3 <= f2) == (f4 >= f1 && f4 <= f2) ) return ans1;
 66             else return ans2;
 67         }
 68         else
 69         {
 70             if((f3 >= f2 && f3 <= f1) == (f4 >=f2 && f4 <= f1) ) return ans1;
 71             else return ans2;
 72         }
 73     }
 74     else
 75     {
 76         if(f2 < f1)
 77         {
 78             if((f3 >= f2 && f3 <= f1) == (f4 >= f2 && f4 <= f1) ) return ans1;
 79             else return ans2;
 80         }
 81         else
 82         {
 83             if((f3 >= f1 && f3 <= f2) == (f4 >= f1 && f4 <= f2)) return ans1;
 84             else return ans2;
 85         }
 86     }
 87 }
 88
 89 int main()
 90 {
 91   //   freopen("in","r",stdin);
 92     int kase = 1;
 93     while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y,&pp.x,&pp.y)!=EOF)
 94     {
 95         pc = get_pc1(p1,p2,p3);
 96         double ans = get_ans(pc,pp,p1,p2,p3);
 97         printf("Case %d: %.3lf\n",kase++,ans);
 98     }
 99     return 0;
100 }

官方标程:

 1 // Rujia Liu
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<iostream>
 5
 6 using namespace std;
 7
 8 const double PI = acos(-1.0);
 9 const double TWO_PI = 2 * PI;
10 const double eps = 1e-6;
11
12 inline double NormalizeAngle(double rad, double center = PI) {
13   return rad - TWO_PI * floor((rad + PI - center) / TWO_PI);
14 }
15
16 inline int dcmp(double x) {
17   if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
18 }
19
20 struct Point {
21   double x, y;
22   Point(double x=0, double y=0):x(x),y(y) { }
23 };
24
25 typedef Point Vector;
26
27 inline Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
28 inline Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
29
30 inline double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }
31 inline double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
32 inline double Length(Vector A) { return sqrt(Dot(A, A)); }
33
34 // 外接圆圆心。假定三点不共线
35 Point get_circumscribed_center(Point p1, Point p2, Point p3) {
36   double bx = p2.x - p1.x;
37   double by = p2.y - p1.y;
38   double cx = p3.x - p1.x;
39   double cy = p3.y - p1.y;
40   double d = 2 * (bx * cy - by * cx);
41   Point p;
42   p.x = (cy * (bx * bx + by * by) - by * (cx * cx + cy * cy)) / d + p1.x;
43   p.y = (bx * (cx * cx + cy * cy) - cx * (bx * bx + by * by)) / d + p1.y;
44   return p;
45 }
46
47 double DistanceToArc(Point a, Point start, Point mid, Point end) {
48   Point p = get_circumscribed_center(start, mid, end);
49   bool CCW = dcmp(Cross(mid - start, end - start)) > 0;
50   double ang_start = atan2(start.y-p.y, start.x-p.x);
51   double ang_end = atan2(end.y-p.y, end.x-p.x);
52   double r = Length(p - start);
53   double ang = atan2(a.y-p.y, a.x-p.x);
54   bool inside;
55   if(CCW) {
56     inside = NormalizeAngle(ang - ang_start) < NormalizeAngle(ang_end - ang_start);
57   } else {
58     inside = NormalizeAngle(ang - ang_end) < NormalizeAngle(ang_start - ang_end);
59   }
60   if(inside) {
61     return fabs(r - Length(p - a));
62   }
63   return min(Length(a - start), Length(a - end));
64 }
65
66 int main() {
67   int kase = 0;
68   double x1, y1, x2, y2, x3, y3, xp, yp;
69   while(cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3 >> xp >> yp) {
70     double ans = DistanceToArc(Point(xp,yp), Point(x1,y1), Point(x2,y2), Point(x3,y3));
71     printf("Case %d: %.3lf\n", ++kase, ans);
72   }
73   return 0;
74 }

时间: 2024-10-10 06:12:06

csuoj 1503: 点到圆弧的距离的相关文章

csu-acm 1503: 点到圆弧的距离

1503: 点到圆弧的距离 分析: 先判断点和圆心的连线是否在圆弧范围内,如果在,最短距离即到圆心的距离减去半径的绝对值:反之,为到端点的最短距离. 具体看注释 #include <bits/stdc++.h> using namespace std; #define eps 1e-8 const double pi=acos(-1); struct Point { double x,y; Point(double a=0,double b=0) { x=a; y=b; } }; Point

CSU 1503: 点到圆弧的距离(计算几何)

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503 Description 输入一个点P和一条圆弧(圆周的一部分),你的任务是计算P到圆弧的最短距离.换句话说,你需要在圆弧上找一个点,到P点的距离最小. 提示:请尽量使用精确算法.相比之下,近似算法更难通过本题的数据. Input 输入包含最多10000组数据.每组数据包含8个整数x1, y1, x2, y2, x3, y3, xp, yp.圆弧的起点是A(x1,y1),经过点B(

CSU 1503 点到圆弧的距离(2014湖南省程序设计竞赛A题)

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503 解题报告:分两种情况就可以了,第一种是那个点跟圆心的连线在那段扇形的圆弧范围内,这样的话点到圆弧的最短距离就是点到圆心的距离减去半径然后再取绝对值就可以了,第二种情况是那个点跟圆心的连线不在那段扇形的圆弧范围内,这样的话,最短的距离就是到这段圆弧的端点的最小值. 接下来的第一步就是求圆心的坐标跟圆的半径,只要求出圆心坐标半径就好说了,求圆心坐标我用的方法是: 设圆心坐标是(a,b

csu 1503: 点到圆弧的距离-湖南省第十届大学生计算机程序设计竞赛

就是--判断p与圆心的连线与圆的交点在不在圆弧上,在就是它到p的距离,不在就是p跟端点的最短距离 #include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector>

点到圆弧的距离(csu1503)+几何

1503: 点到圆弧的距离 Time Limit: 1 Sec  Memory Limit: 128 MB  Special JudgeSubmit: 325  Solved: 70[Submit][Status][Web Board] Description 输入一个点P和一条圆弧(圆周的一部分),你的任务是计算P到圆弧的最短距离.换句话说,你需要在圆弧上找一个点,到P点的距离最小.提示:请尽量使用精确算法.相比之下,近似算法更难通过本题的数据. Input 输入包含最多10000组数据.每组

5-7 点到原点的距离(多态)

给出下面的一个基类框架: class Point { protected: int dimension;//点的维数,最多不超过100维 private: int point_length[100]://点数组 public: Point ();//构造函数根据需要重载 float distance( );//计算当前点到原点的距离 void display();//输出点 } 以Point为基类建一个派生类Point_2D,增加以下数据成员: float x;//2D平面上点的x坐标 floa

POJ1584 判断多边形是否为凸多边形,并判断点到直线的距离

求点到直线的距离: double dis(point p1,point p2){   if(fabs(p1.x-p2.x)<exp)//相等的  {    return fabs(p2.x-pegx);    }  else     {   double k=(p2.y-p1.y)/(p2.x-p1.x);   double b=p2.y-k*p2.x;   return fabs(k*pegx-pegy+b)/sqrt(k*k+1);//返回的是距离的   }}判断多边形是否为凸多边形 if

URAL 1348 Goat in the Garden 2(点到线段的距离)

[题目链接]:click here~~ [题目大意]:求某点到一条线段的最小距离与最大距离. [思路]: 分析可知,最大距离一定在端点处取得.那么接下来求最小距离时,先求出垂线与线段所在直线的交点,然后判断交点在不在线段上.如果在,则最小距离为垂线段的距离,即交点到此点的距离.如果不在,则最小距离必在另一端点取得.问题转换如何判断点与线段的垂足是否在线段上,可以利用叉积方便的求出. 代码: /* * Problem: NO:URAL 1348 * Running time: 1MS * Comp

poj1584 A Round Peg in a Ground Hole 判断多边形凹凸,点到线的距离【基础计算几何】

大致思路:首先对于所给的洞的点,判断是否是凸多边形,图形的输入和输出可以是顺时针或者逆时针,而且允许多点共线 Debug 了好几个小时,发现如下问题 判断三点是否共线,可用斜率公式判断 POINT point_A, point_B, point_C; if(point_A.x == point_B.x || point_B.x == point_C.x){ if(point_A.x == point_B.x && point_B.x == point_C.x) continue; }els