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代码:

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps = 1e-,PI = acos(-1.0); struct Point
{
double x,y;
friend Point operator - (Point a,Point b)
{
Point temp;
temp.x = a.x - b.x;
temp.y = a.y - b.y;
return temp;
}
}; Point p1,p2,p3,pc,pp;
double r; Point get_pc1(Point p1, Point p2, Point p3) //求圆心
{
Point p;
if(fabs(p1.y-p2.y) > eps) //因为计算过程中有出现(y2-y1)做分母的情况,所以这里分了两种情况讨论
{
// 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);
// double t2 = 2.0*(p3.x-p1.x)-(2*(p3.y-p1.y)*(p2.x-p1.x)) / (p2.y-p1.y);
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);
double t2 = 2.0*((p3.y-p1.y)*(p2.x-p1.x) - (p2.y-p1.y)*(p3.x-p1.x));
p.x = t1 / t2;
p.y = (p2.x*p2.x-p1.x*p1.x+p2.y*p2.y-p1.y*p1.y-*(p2.x-p1.x)*p.x) / (*(p2.y-p1.y));
}
else
{
p.x = (p2.x*p2.x-p1.x*p1.x+p2.y*p2.y-p1.y*p1.y) / (*(p2.x-p1.x));
p.y = (p3.x*p3.x-p1.x*p1.x+p3.y*p3.y-p1.y*p1.y-*(p3.x-p1.x)*p.x) / (*(p3.y-p1.y));
}
return p;
}
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 mult_ca(Point p1,Point p2) //叉乘
{
return p1.x * p2.y - p2.x * p1.y;
} double get_ans(Point pc,Point pp,Point p1,Point p2,Point p3)
{
double temp = mult_ca(p2-p1,p3-p1);
double f1 = atan2((p1-pc).x,(p1-pc).y);
double f2 = atan2((p3-pc).x,(p3-pc).y);
double f3 = atan2((p2-pc).x,(p2-pc).y);
double f4 = atan2((pp-pc).x,(pp-pc).y);
double ans1 = fabs(dis(pp,pc)-dis(p1,pc));
double ans2 = min(dis(pp,p1),dis(pp,p3));
if(temp < ) //顺时针给点
{
if(f1 < f2) //判断区间方向,这样有利于判断p点和p2点是不是在同一个区间
{
if((f3 >= f1 && f3 <= f2) == (f4 >= f1 && f4 <= f2) ) return ans1;
else return ans2;
}
else
{
if((f3 >= f2 && f3 <= f1) == (f4 >=f2 && f4 <= f1) ) return ans1;
else return ans2;
}
}
else
{
if(f2 < f1)
{
if((f3 >= f2 && f3 <= f1) == (f4 >= f2 && f4 <= f1) ) return ans1;
else return ans2;
}
else
{
if((f3 >= f1 && f3 <= f2) == (f4 >= f1 && f4 <= f2)) return ans1;
else return ans2;
}
}
} int main()
{
// freopen("in","r",stdin);
int kase = ;
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)
{
pc = get_pc1(p1,p2,p3);
double ans = get_ans(pc,pp,p1,p2,p3);
printf("Case %d: %.3lf\n",kase++,ans);
}
return ;
}

官方标程:

 // Rujia Liu
#include<cmath>
#include<cstdio>
#include<iostream> using namespace std; const double PI = acos(-1.0);
const double TWO_PI = * PI;
const double eps = 1e-; inline double NormalizeAngle(double rad, double center = PI) {
return rad - TWO_PI * floor((rad + PI - center) / TWO_PI);
} inline int dcmp(double x) {
if(fabs(x) < eps) return ; else return x < ? - : ;
} struct Point {
double x, y;
Point(double x=, double y=):x(x),y(y) { }
}; typedef Point Vector; inline Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
inline Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } inline double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }
inline double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
inline double Length(Vector A) { return sqrt(Dot(A, A)); } // 外接圆圆心。假定三点不共线
Point get_circumscribed_center(Point p1, Point p2, Point p3) {
double bx = p2.x - p1.x;
double by = p2.y - p1.y;
double cx = p3.x - p1.x;
double cy = p3.y - p1.y;
double d = * (bx * cy - by * cx);
Point p;
p.x = (cy * (bx * bx + by * by) - by * (cx * cx + cy * cy)) / d + p1.x;
p.y = (bx * (cx * cx + cy * cy) - cx * (bx * bx + by * by)) / d + p1.y;
return p;
} double DistanceToArc(Point a, Point start, Point mid, Point end) {
Point p = get_circumscribed_center(start, mid, end);
bool CCW = dcmp(Cross(mid - start, end - start)) > ;
double ang_start = atan2(start.y-p.y, start.x-p.x);
double ang_end = atan2(end.y-p.y, end.x-p.x);
double r = Length(p - start);
double ang = atan2(a.y-p.y, a.x-p.x);
bool inside;
if(CCW) {
inside = NormalizeAngle(ang - ang_start) < NormalizeAngle(ang_end - ang_start);
} else {
inside = NormalizeAngle(ang - ang_end) < NormalizeAngle(ang_start - ang_end);
}
if(inside) {
return fabs(r - Length(p - a));
}
return min(Length(a - start), Length(a - end));
} int main() {
int kase = ;
double x1, y1, x2, y2, x3, y3, xp, yp;
while(cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3 >> xp >> yp) {
double ans = DistanceToArc(Point(xp,yp), Point(x1,y1), Point(x2,y2), Point(x3,y3));
printf("Case %d: %.3lf\n", ++kase, ans);
}
return ;
}

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

  1. csu 1503: 点到圆弧的距离

    1503: 点到圆弧的距离 Time Limit: 1 Sec  Memory Limit: 128 MB  Special JudgeSubmit: 614  Solved: 101[Submit] ...

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

    1503: 点到圆弧的距离 分析: 先判断点和圆心的连线是否在圆弧范围内,如果在,最短距离即到圆心的距离减去半径的绝对值:反之,为到端点的最短距离. 具体看注释 #include <bits/s ...

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

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

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

    题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503 解题报告:分两种情况就可以了,第一种是那个点跟圆心的连线在那段扇形的圆弧范围内,这 ...

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

    1503: 点到圆弧的距离 Time Limit: 1 Sec  Memory Limit: 128 MB  Special JudgeSubmit: 325  Solved: 70[Submit][ ...

  6. csu 1503: 点弧之间的距离-湖南省第十届大学生计算机程序设计大赛

    这是--比量p并用交点连接中心不上弧.在于:它至p距离.是不是p与端点之间的最短距离 #include<iostream> #include<map> #include< ...

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

    求点到直线的距离: double dis(point p1,point p2){   if(fabs(p1.x-p2.x)<exp)//相等的  {    return fabs(p2.x-pe ...

  8. ArcGIS 点到直线的距离

    /****点到直线的距离*** * 过点(x1,y1)和点(x2,y2)的直线方程为:KX -Y + (x2y1 - x1y2)/(x2-x1) = 0 * 设直线斜率为K = (y2-y1)/(x2 ...

  9. LA 3027 Corporative Network 并查集记录点到根的距离

    Corporative Network Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [S ...

随机推荐

  1. bug:[NSKeyedUnarchiver initForReadingWithData:]: data is NULL

    一,经历 1.问题出在给NSMutableDictionary类型的字典设置内容上. [_dictRateApp setObject:[NSNumber numberWithBool:NO] forK ...

  2. iOS 自动布局小结

    1> sizeclasses 可以限制某个 storyboard 显示在什么样的屏幕上,如 当前 storyboard 在iPhone 的左斜右斜或 iPad上是否显示.. 2> Hug值 ...

  3. Node.js的高性能封装 Express.js

    Express 是一个简洁而灵活的 node.js Web应用框架, 提供一系列强大特性帮助你创建各种Web应用.Express 不对 node.js 已有的特性进行二次抽象,我们只是在它之上扩展了W ...

  4. EditText自定义边框

    1.EditText代码如下 (View代替EditText获取焦点): <View android:focusable="true" android:focusableIn ...

  5. [LintCode] Longest Consecutive Sequence 求最长连续序列

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. H ...

  6. php中提示Undefined index的解决方法

    我们经常接收表单POST过来的数据时报Undefined index错误,如下: $act=$_POST['action']; 用以上代码总是提示 Notice: Undefined index: a ...

  7. 第一次scrum meeting 报告

    1.第一次scrum meeting确定了我们任务和相应的分配方案,具体分配情况如下: 这是我们团队其中一名成员的任务内容及相应预估时长,其他成员具体分配情况已在TFS上作了相应更新. 第一次scru ...

  8. cloudsim安装,配置(到eclipse)

    现在基本成功了.所以将这个过程尽量详细的,准确的分享出来,以供大家的需要.       一.Jdk,Eclipse的安装与配置. 本人下载的jdk版本是1.8,jdk的相关配置网上有很多,我就不赘述了 ...

  9. 示例说明Oracle RMAN两种库增量备份的差别

    1差异增量实验示例 1.1差异增量备份 为了演示增量备份的效果,我们在执行一次0级别的备份后,对数据库进行一些改变. 再执行一次1级别的差异增量备份: 执行完1级别的备份后再次对数据库进行更改: 再执 ...

  10. window.open()&&window.showmodaldialog()

    open 打开一个新窗口,并装载URL指定的文档,或装载一个空白文档,如果没提供URL的话. 适用于 窗口 语法 window = object.open([URL[,name[,features[, ...