题目链接: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三分
题目意思:给出两条线段,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;
}