题目描述

输入一个点 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 0 1 1 2 0 1 -1
3 4 0 5 -3 4 0 1

样例输出

Case 1: 1.414
Case 2: 4.000

分两种情况:

第一种:点跟圆心的连线在那段扇形的圆弧范围内,点到圆弧的最短距离为点到圆心的距离减去半径然后取绝对值;

第二种:点跟圆心的连线不在那段扇形的圆弧范围内,点到圆弧的最短的距离为到这段圆弧的两个端点的最小值。

 #include <bits/stdc++.h>
using namespace std;
const double eps = 1e-;
const double PI = acos(-1.0);
int casee = ;
int dcmp(double x) {
if(fabs(x) < eps) return ;
else return x < ? - : ;
}
struct Vector {
double x, y;
Vector(double x_ = , double y_ = ) : x(x_), y(y_) {} Vector operator+ (const Vector &a) const {
return Vector(x + a.x, y + a.y);
}
Vector operator- (const Vector &a) const {
return Vector(x - a.x, y - a.y);
}
Vector operator* (double p) {
return Vector(x * p, y * p);
}
friend Vector operator* (double p, const Vector &a) {
return Vector(a.x * p, a.y * p);
}
Vector operator/ (double p) {
return Vector(x / p, y / p);
}
bool operator== (const Vector &a) const {
return dcmp(x - a.x) == && dcmp(y - a.y) == ;
} friend double dmul(const Vector &a, const Vector &b) {
return a.x * b.x + a.y * b.y;
}
friend double cmul(const Vector &a, const Vector &b) {
return a.x * b.y - a.y * b.x;
}
friend double angle(const Vector &a, const Vector &b) {
return acos(dmul(a, b) / a.length() / b.length());
}
friend Vector rotate(const Vector &a, double rad) {
return Vector(a.x * cos(rad) - a.y * sin(rad), a.x * sin(rad) + a.y * cos(rad));
}
friend Vector normal(const Vector &a) {
double l = a.length();
return Vector(a.x / l, a.y / l);
} double length() const {
return sqrt(dmul(*this, *this));
}
};
typedef Vector Point;
double dis(Point A, Point B) {
return (A-B).length();
}
Point pp1, pp2, pp3, pp, o; Point get_cir(Point a,Point b,Point c) {//已知圆上3点,求圆的外心
double a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/;
double a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/;
double d=a1*b2-a2*b1;
return Point(a.x+(c1*b2-c2*b1)/d,a.y+(a1*c2-a2*c1)/d);
}
double AngleToX(Vector A, Vector B) {//向量与x轴正方向的夹角,范围[0,2*pi) B为(1,0)
double res = angle(A, B);
if(dcmp(cmul(A, B)) < ) res = PI * - res;
return res;
}
void gao (Point A,Point B,Point C,Point P,Point O)
{
Vector X(, );
Vector OA = A - O, OP = P - O, OC = C - O, OB = B - O;
double fa = AngleToX(OA, X);
double fb = AngleToX(OB, X);
double fc = AngleToX(OC, X);
double fp = AngleToX(OP, X);
double ans = min(dis(P, A), dis(P, C));
double r = dis(A, O);
if(fa>fc) swap(fa,fc);
if(dcmp(fa-fb)<= && dcmp(fb - fc) <= && dcmp(fa - fp) <= && dcmp(fp - fc) <= ) {
double r = dis(A, O);
ans = min(ans, fabs(dis(O, P) - r));
}
if(!(dcmp(fa - fb) <= &&dcmp(fb-fc)<= )&&!(dcmp(fa-fp)<=&&dcmp(fp-fc)<=)) {
ans = min(ans, fabs(dis(O, P)- r));
} printf("Case %d: %.3f\n", ++casee, ans);
}
int main() {
while(~scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &pp1.x,&pp1.y,&pp2.x,&pp2.y,&pp3.x,&pp3.y,&pp.x,&pp.y)){
o=get_cir(pp1,pp2,pp3);
gao(pp1,pp2,pp3,pp,o);
}
return ;
}

解法2

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#define eps (1e-4)
#define N 205
#define dd double
#define sqr(x) ((x)*(x))
const double pi = acos(-);
using namespace std;
struct Point
{
double x,y;
};
double cross(Point a,Point b,Point c) ///叉积
{
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
double dis(Point a,Point b) ///距离
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
Point waixin(Point a,Point b,Point c) ///外接圆圆心坐标
{
Point p;
double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1*a1 + b1*b1)/;
double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2*a2 + b2*b2)/;
double d = a1*b2 - a2*b1;
p.x = a.x + (c1*b2 - c2*b1)/d, p.y=a.y + (a1*c2 -a2*c1)/d;
return p;
}
bool judge(Point a,Point b,Point c,Point p){ ///此模板判断点 p 是否在两条射线 ab 和 ac 之间(但是p点不在 ab或者 ac上)
if(cross(b,c,a)>&&cross(p,a,c)<&&cross(p,a,b)>){ ///b 在 c 的逆时针方向
return true;
}
if(cross(b,c,a)<&&cross(p,a,c)>&&cross(p,a,b)<){ ///b 在 c 的顺时针方向
return true;
}
return false;
}
bool judge1(Point a,Point b,Point c,Point p){ ///此模板判断点 p 是否在两条射线 ab 和 ac 之间(p点可以在 ab或者 ac上)
if(cross(b,c,a)>&&cross(p,a,c)<=&&cross(p,a,b)>=){ ///b 在 c 的逆时针方向
return true;
}
if(cross(b,c,a)<&&cross(p,a,c)>=&&cross(p,a,b)<=){ ///b 在 c 的顺时针方向
return true;
}
return false;
}
int main()
{
Point a,b,c,p;
int t = ;
freopen("a.in","r",stdin);
freopen("a.txt","w",stdout);
while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&p.x,&p.y)!=EOF)
{ Point circle = waixin(a,b,c);
double r = dis(circle,a);
double ans = min(dis(p,a),dis(p,c));
double op = dis(circle,p);
if(fabs(*r-dis(a,c))<eps){ ///平角特殊处理
if(cross(p,c,circle)*cross(b,c,circle)>=){
ans = min(ans,fabs(op-r));
}
printf("Case %d: %.3lf\n",t++,ans);
continue;
}
if(judge(circle,a,c,b)) ///劣弧
{
if(judge1(circle,a,c,p)) ans = min(ans,fabs(op-r));
}
else
{
if(!judge(circle,a,c,p)) ans = min(ans,fabs(op-r));
}
printf("Case %d: %.3lf\n",t++,ans);
}
}

标程:

 // 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 ;
}

CSU 1503: 点到圆弧的距离(计算几何)的更多相关文章

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

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

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

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

  3. csuoj 1503: 点到圆弧的距离

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503 1503: 点到圆弧的距离 时间限制: 1 Sec  内存限制: 128 MB  Speci ...

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

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

  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. hdu 1174:爆头(计算几何,三维叉积求点到线的距离)

    爆头 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...

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

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

  9. ArcGIS 点到直线的距离

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

随机推荐

  1. 升级至webpack4.x踩坑记(热更新局部更新失败的问题修复)

    零.前言 webpack升级的时候,会碰到各种个样的问题,大多数网上都能查到解决方案最简单的方案. 思路如下: 1.把css-loader,xxxloader等依赖都升级到最新 2.根据webpack ...

  2. swiper在vue中的用法

    首先通过npm i vue-awesome-swiper --save 来在vue中下载插件 然后再main.js中引入 require('swiper/dist/css/swiper.css')im ...

  3. 测开之路七十九:python 文件处理和对象的写入读取

    """处理文件:open(文件名, 模式,编码) 'r' 打开阅读(默认)'w' 打开写入,首先截断文件'x' 打开独占创建,如果文件已经存在则失败'a' 打开写入,追加 ...

  4. python判断字符串是否是json格式方法分享

    python判断字符串是否是json格式方法分享 在实际工作中,有时候需要对判断字符串是否为合法的json格式 解决方法使用json.loads,这样更加符合'Pythonic'写法 代码示例:   ...

  5. c++ 由无向图构造邻接表,实现深度优先遍历、广度优先遍历。

    /* 首先,根据用户输入的顶点总数和边数,构造无向图,然后以用户输入的顶点 为起始点,进行深度优先.广度优先搜索遍历,并输出遍历的结果. */ #include <stdlib.h> #i ...

  6. win10下装win7双系统安装教程

    win10下装win7双系统安装教程 来源:www.laomaotao.org 时间:2017-02-13 10:15 新买的电脑预装了win10系统,但win10对于有些游戏兼容性不是很好,总是会出 ...

  7. 索引及explain

    索引好比书的目录.通过索引能快速的定位到一条数据. 在MySQL中除了B+树索引之外,还有一些其他的索引类型.比如:全文索引.(DB和DD索引叫R树索引).在MySQL cluster中是P树索引,m ...

  8. mysql高级知识

    2 数据约束 2.1什么数据约束 ​ 对用户操作表的数据进行约束 2.2 默认值 作用: 当用户对使用默认值的字段不插入值的时候,就使用默认值. 注意: 1)对默认值字段插入null是可以的. 2)对 ...

  9. UVALive 6270 Edge Case(找规律,大数相加)

    版权声明:本文为博主原创文章,未经博主同意不得转载. vasttian https://blog.csdn.net/u012860063/article/details/36905379 转载请注明出 ...

  10. 用Fusion Log诊断同一版本冲突问题解决

    处理方法,修改注册表 Add the following values to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion Add: DWORD Force ...