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代码:
#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: 点到圆弧的距离的更多相关文章
- csu 1503: 点到圆弧的距离
1503: 点到圆弧的距离 Time Limit: 1 Sec Memory Limit: 128 MB Special JudgeSubmit: 614 Solved: 101[Submit] ...
- csu-acm 1503: 点到圆弧的距离
1503: 点到圆弧的距离 分析: 先判断点和圆心的连线是否在圆弧范围内,如果在,最短距离即到圆心的距离减去半径的绝对值:反之,为到端点的最短距离. 具体看注释 #include <bits/s ...
- CSU 1503: 点到圆弧的距离(计算几何)
题目描述 输入一个点 P 和一条圆弧(圆周的一部分),你的任务是计算 P 到圆弧的最短距离.换句话 说,你需要在圆弧上找一个点,到 P点的距离最小. 提示:请尽量使用精确算法.相比之下,近似算法更难通 ...
- CSU 1503 点到圆弧的距离(2014湖南省程序设计竞赛A题)
题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503 解题报告:分两种情况就可以了,第一种是那个点跟圆心的连线在那段扇形的圆弧范围内,这 ...
- 点到圆弧的距离(csu1503)+几何
1503: 点到圆弧的距离 Time Limit: 1 Sec Memory Limit: 128 MB Special JudgeSubmit: 325 Solved: 70[Submit][ ...
- csu 1503: 点弧之间的距离-湖南省第十届大学生计算机程序设计大赛
这是--比量p并用交点连接中心不上弧.在于:它至p距离.是不是p与端点之间的最短距离 #include<iostream> #include<map> #include< ...
- POJ1584 判断多边形是否为凸多边形,并判断点到直线的距离
求点到直线的距离: double dis(point p1,point p2){ if(fabs(p1.x-p2.x)<exp)//相等的 { return fabs(p2.x-pe ...
- ArcGIS 点到直线的距离
/****点到直线的距离*** * 过点(x1,y1)和点(x2,y2)的直线方程为:KX -Y + (x2y1 - x1y2)/(x2-x1) = 0 * 设直线斜率为K = (y2-y1)/(x2 ...
- LA 3027 Corporative Network 并查集记录点到根的距离
Corporative Network Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu [S ...
随机推荐
- BestCoder Round #77
T1 xiaoxin juju needs help 计算组合数然后多重集排列乱搞,注意判无解情况(TM我就判错然后FST了). #include<cstdio> #include< ...
- 让 cell 显示底部线条时,总是有几个线条被隐藏.
一,经历 1> 感觉像是重用的问题,但从代码的分析中找不出任何问题. 2> 感觉像是我 在创建怎样的 cell 的代码 被 layoutsubviews 方法覆盖了一样.于是先在创建怎样的 ...
- PHP面向对象学习六 多态
OOP的模式并不仅仅是把很多函数和功能集合起来,目的而是使用类,继承,多态的方式描述我们生活中的一种情况.从而使得我们的代码更具有“物”的意义.帮助我们减少一些重复性的代码和条件语句的判断. 运算 ...
- Linux下设置svn过滤文件类型
1)修改客户端. 1.修改客户端 1)编辑文件家目录下自己账户下的.subversion/config文件 vim ~/.subversion/config 2)找到包含[miscellany]的一行 ...
- mysql双主复制总结
双主复制: 1).在两台服务器上各自建立一个具有复制权限的用户: 2).修改配置文件: # 主服务器A上 [mysqld] server-id = 10 log-bin = mysql-bin rel ...
- thinkphp关联模型的用法
HAS_ONE(值得注意的是,这是主动关联,外键必须是被关联的表): <?php namespace Home\Model; use Think\Model\RelationModel; cla ...
- oracle 学习摘录
(1)oracle插入回车换行符 SQL>insert into A t(t.name) values('aaaaa'||chr(10)||chr(13)||'ccccc'); 已创建 1 行. ...
- 一个参数大小写引发的uploadify报错 "Syntax error, unrecognized expression: #"
上传控件uploadify 报错"Syntax error, unrecognized expression: #" 版本为 uploadify3.2 报错原因:参数ID[hi ...
- 微信小程序学习
官方网站 https://mp.weixin.qq.com/debug/wxadoc/dev/index.html 项目结构介绍 -- MINA框架 https://mp.weixin.qq.com/ ...
- 歐洲國家拓展其移動和IT服務業務
中興德國子公司與JOIN簽訂了一項綜合託管服務合同,在該合同中,公司將全面負責為盧森堡和比利時的JOIN核心網路提供網路運營,點對點無線網路報告,新品發佈和維護,還負責故障檢查.維修.測試和軟體升級. ...