hdu3400 Line belt 三分法

来源:互联网 发布:电子琴知乎 编辑:程序博客网 时间:2024/04/27 23:31
题目链接: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-8struct 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;elseleft = 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;elseleft = mid;} while (dist(right, left) > eps);printf("%.2lf\n", min(ans1, ans2));}return 0;}


原创粉丝点击