pc 111302 uva 10180 Rope Crisis in Ropeland!

本文介绍了一种判断线段与圆是否相交的方法,并给出相应的C++代码实现。重点在于通过点到直线的距离及叉积判断相交情况,同时计算相交时圆弧段的长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[size=large][color=darkblue]题目描述:[/color][/size]
[url]http://www.programming-challenges.com/pg.php?page=downloadproblem&probid=111302&format=html[/url]
[color=red]另外做该题的时候参考了ybfq_wanglang的解题思路,地址如下:[/color]
[url]http://hi.baidu.com/ybfq_wanglang/blog/item/9fff3b0d116176206159f33d.html[/url]

//该题关键在于判断线段是否与圆相交
//具体解释参见代码注释
//还有就是该题不用求切点坐标
//利用弧度完成圆弧段的长度计算
//用到反余弦函数
#include <cstdio>
#include <cmath>
#define eps 1e-8

struct point {
double x, y;
};

struct line {
point a, b;
};
//叉积
double xmult(point p1, point p2, point p0) {
return (p1.x - p0.x) * (p2.y - p0.y) -
(p2.x - p0.x) * (p1.y - p0.y);
}
//计算两点间距离
double distance(point p1, point p2) {
return sqrt((p1.x - p2.x) * (p1.x - p2.x) +
(p1.y - p2.y) * (p1.y - p2.y));
}
//计算点到直线距离
double disptoline(point p, point l1, point l2) {
return fabs(xmult(p, l1, l2)) / distance(l1, l2);
}

//判断线段(端点都在圆外)和圆相交,不包括端点和相切
int intersect_seg_circle(point c, double r, point l1, point l2) {
point t = c;
t.x += l1.y - l2.y;
t.y += l2.x - l1.x;
//点t点c构成l1 l2 的垂线,如果l1 l2 在直线t c异侧 ,
//且圆心到l1 l2 的距离小于 r,则l1 l2 与圆相交
return xmult(l1, c, t) * xmult(l2, c, t) < eps &&
disptoline(c, l1, l2) < r;
}


int main() {
point p1, p2, origin; //origin为圆心
origin.x = origin.y = 0.0;
double r;
int ncase;
scanf("%d", &ncase);
while(ncase--) {
scanf("%lf %lf %lf %lf %lf", &p1.x, &p1.y, &p2.x, &p2.y, &r);
double d1 = distance(p1, p2); //点p1 p2间的距离
if(!intersect_seg_circle(origin, r, p1, p2)) //如果线段与圆不想交
printf("%.3lf\n", d1);
else {
double d2 = distance(origin, p1);
double d3 = distance(origin, p2);
double d = sqrt(d2 * d2 - r * r);
d += sqrt(d3 * d3 - r * r);
double t = acos((d2 * d2 + d3 * d3 - d1 * d1) / (2 * d2 * d3));
t -= acos(r / d2) + acos(r / d3); //现在t为圆上的绳子对应的圆心角的弧度
d += t * r;
printf("%.3lf\n", d);
}
}
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值