hdu3400 Line belt 三分法

题目链接:http: //acm.hdu.edu.cn/showproblem.php?pid=3400


题目意思:给出两条线段,AB,CD;并分别给出在这两条线段上的速率p,q;还有在其它地方的速率r;
求A到D的最少时间。


题解:令ab为AB上一点,cd为CD上一点。 则结果为

t= dist( ab ,a)/p + dist (cd ,ab)/r + dist(cd, d)/q
=sqrt( (a.x-ab.x)^2 + (a.y- ab.y )^2 )/p + sqrt( (d.x-cd.x)^2 + (d.y- cd.y )^2 )/q+sqrt ((ab.x- cd.x)^2 + (ab.y- cd.y )^2 )/r
假设cd已知, 对ab点而言,它的纵坐标可以由它的横坐标确定。最终的式子类型是:
sqrt( a1x^2 +b1x+c1 ) +sqrt( a2x^2 +b2x+c2 ) 其中 (a1x^2 +b1x+c1 >=0 , a2x^2 +b2x+c2 >=0)


在这里想证明一下它的单调性,没想到证不出来。。。只是给了个sqrt(x^2-2x+2)+sqrt(x^2-3x+5) 以精度为0.1 打印了一下结果,发现先递减再递加。。。。。。


所以,先对CD三分,再对AB三分


代码如下:


#include<iostream>
#include<cstdio>
#include<math.h>
#define eps 1e-8
struct point
{
	double x,y;
};
point a, b, c, d;
double p, q, r;
double dist(point p1, point p2) {
	return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
point getmid(point p1, point p2) {
	point ret;
	ret.x = (p1.x + p2.x) / 2.0;
	ret.y = (p1.y + p2.y) / 2.0;
	return ret;
}
double min(double a, double b) {
	return a < b ? a : b;
}
double getans(point ab, point cd) {
	return dist(ab, a) / p + dist(cd, ab) / r + dist(cd, d) / q;
}
double three(point cd) //a~b
		{
	point left = a, right = b;
	double temp1 = 0, temp2 = 0;
	do {
		point mid = getmid(left, right), midmid = getmid(mid, right);
		temp1 = getans(mid, cd);
		temp2 = getans(midmid, cd);
		if (temp1 < temp2)
			right = midmid;
		else
			left = mid;
	} while (dist(right, left) > eps);
	return min(temp1, temp2);
}
int main() {
	int cas;
	scanf("%d", &cas);
	while (cas--) {
		scanf("%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y);
		scanf("%lf%lf%lf%lf", &c.x, &c.y, &d.x, &d.y);
		scanf("%lf%lf%lf", &p, &q, &r);
		point left = d, right = c;
		double ans1 = 0, ans2 = 0;
		do {
			point mid = getmid(left, right), midmid = getmid(mid, right);
			ans1 = three(mid);
			ans2 = three(midmid);
			if (ans1 < ans2)
				right = midmid;
			else
				left = mid;
		} while (dist(right, left) > eps);
		printf("%.2lf\n", min(ans1, ans2));
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值