第1部分 基礎算法(提高篇)--第2章 二分與三分1439:【SCOI2010】傳送帶

1439:【SCOI2010】傳送帶

時間限制: 2000 ms 內存限制: 65536 KB
提交數: 372 通過數: 212
【題目描述】
在一個2維平面上有兩條傳送帶,每一條傳送帶可以看成是一條線段。兩條傳送帶分別爲線段AB和線段CD。lxhgww在AB上的移動速度爲P,在CD上的移動速度爲Q,在平面上的移動速度R。現在lxhgww想從A點走到D點,他想知道最少需要走多長時間。

【輸入】
輸入數據第一行是4個整數,表示A和B的座標,分別爲Ax,Ay,Bx,By

第二行是4個整數,表示C和D的座標,分別爲Cx,Cy,Dx,Dy

第三行是3個整數,分別是P,Q,R

【輸出】
輸出數據爲一行,表示lxhgww從A點走到D點的最短時間,保留到小數點後2位

【輸入樣例】
0 0 0 100
100 0 100 100
2 2 1
【輸出樣例】
136.60
【提示】
【數據範圍】

對於100%的數據,1≤ Ax,Ay,Bx,By,Cx,Cy,Dx,Dy≤1000

1≤P,Q,R≤10


思路:有兩條線段AB,CD,在AB上行走的速度爲p,CD上行走的速度爲q,平面裏行走的速度爲r(r>p,q)。求從A走到D的最短距離。

路線都是AE—EF—FD,不妨先把E點定下來,現在要求EF/r+FD/q的最小值,用勾股定理的表示出來發現它是一個單峯函數,是可以用三分法求出來的。
在這裏插入圖片描述
————————————————

#include<bits/stdc++.h>
#define eps 1e-8
using namespace std;
struct Point{
	double x,y;
	Point(){};
	Point(double xx,double yy):x(xx),y(yy){};
	Point operator / (double a){return Point(x/a, y/a);}
	Point operator - (const Point &a){return Point(x-a.x, y-a.y);}
	Point operator + (const Point &a){return Point(x+a.x, y+a.y);}
}A,B,C,D;
double P,Q,R;
double dis(Point a,Point b){
	return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
double calc(Point X){
	Point l = C, r = D;
	while(dis(l,r) > eps){
		Point x = (r - l) / 3;
		Point lmid = l + x, rmid = r - x;
		double ans1 = dis(lmid,D)/Q + dis(X,lmid)/R;
		double ans2 = dis(rmid,D)/Q + dis(X,rmid)/R;
		if(ans2 - ans1 > eps) r = rmid;
		else l = lmid;
	} return dis(l,D)/Q + dis(X,l)/R;
}
double Solve(){
	Point l = A, r = B;
	while(dis(l,r) > eps){
		Point x = (r - l) / 3;
		Point lmid = l + x, rmid = r - x;
		double ans1 = calc(lmid) + dis(lmid, A)/P;
		double ans2 = calc(rmid) + dis(rmid, A)/P;
		if(ans2 - ans1 > eps) r = rmid;
		else l = lmid;
	} return calc(l) + dis(l,A)/P;
}
int main(){
	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);
	printf("%0.2lf", Solve()); return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章