CSU 1503: 点到圆弧的距离(计算几何)
题目描述
提示:请尽量使用精确算法。相比之下,近似算法更难通过本题的数据。
输入
输出
样例输入
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: 点到圆弧的距离(计算几何)的更多相关文章
- csu 1503: 点到圆弧的距离
1503: 点到圆弧的距离 Time Limit: 1 Sec Memory Limit: 128 MB Special JudgeSubmit: 614 Solved: 101[Submit] ...
- CSU 1503 点到圆弧的距离(2014湖南省程序设计竞赛A题)
题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503 解题报告:分两种情况就可以了,第一种是那个点跟圆心的连线在那段扇形的圆弧范围内,这 ...
- csuoj 1503: 点到圆弧的距离
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1503 1503: 点到圆弧的距离 时间限制: 1 Sec 内存限制: 128 MB Speci ...
- csu-acm 1503: 点到圆弧的距离
1503: 点到圆弧的距离 分析: 先判断点和圆心的连线是否在圆弧范围内,如果在,最短距离即到圆心的距离减去半径的绝对值:反之,为到端点的最短距离. 具体看注释 #include <bits/s ...
- 点到圆弧的距离(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< ...
- hdu 1174:爆头(计算几何,三维叉积求点到线的距离)
爆头 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...
- 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 ...
随机推荐
- c++函数overload 的歧义匹配
https://www.zhihu.com/question/20200615 函数重载选择最佳匹配函数涉及到类型转换,默认参数 注意:没有int f(int,int)版本,编译器认为上面两个函数都是 ...
- 【EWM系列】SAP EWM模块-修改任何内容都报错
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[EWM系列]SAP EWM模块-修改任何内容都 ...
- vuejs基础-v-for用法
Vue指令之v-for和key属性 迭代数组 <ul> <li v-for="(item, i) in list">索引:{{i}} --- 姓名:{{it ...
- 如何配置JedisPool的参数
转自:http://blog.csdn.net/huahuagongzi99999/article/details/13631579 如何配置Pool的参数 JedisPool的配置参数很大程度上依赖 ...
- [Python3] 022 面向对象 第二弹
目录 6. 面向对象的三大特性 6.1 封装 6.1.1 私有 private 6.1.2 受保护 protected 6.1.3 公开 public 6.2 继承 6.2.1 继承的概念与作用 6. ...
- Netty之Page级别的内存分配
Page 级别的内存分配: 之前我们介绍过, netty 内存分配的单位是chunk, 一个chunk 的大小是16MB, 实际上每个chunk, 都以双向链表的形式保存在一个chunkList 中, ...
- SpringMvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- Ubuntu12.04下安装Subversion并进行配置
Ubuntu下安装Subversion还是很简单的,只要输入sudo apt-get install Subversion就可以安装了. 主要的难点在于对权限的配置上. 安装完subversion后, ...
- 使用requests_html抓取数据
from requests_html import HTMLSession import json class YejiCollege: def __init__(self, url): self.u ...
- jvm(4) 对象创建
1.对象的创建过程: 1.new 类名 2.根据new的参数在常量池中定位一个类的符号的引用. 3.如果没找到这个符号的引用,说明类还没有被加载.则进行类的加载,解析和初始化 4.虚拟机为对象分配内存 ...