`
scott________
  • 浏览: 20773 次
  • 性别: Icon_minigender_1
  • 来自: 哈尔滨
最近访客 更多访客>>
社区版块
存档分类
最新评论

pc 111302 uva 10180 Rope Crisis in Ropeland!

阅读更多
题目描述:
http://www.programming-challenges.com/pg.php?page=downloadproblem&probid=111302&format=html
另外做该题的时候参考了ybfq_wanglang的解题思路,地址如下:
http://hi.baidu.com/ybfq_wanglang/blog/item/9fff3b0d116176206159f33d.html
//该题关键在于判断线段是否与圆相交
//具体解释参见代码注释
//还有就是该题不用求切点坐标
//利用弧度完成圆弧段的长度计算
//用到反余弦函数
#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;
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics