1. 程式人生 > >BZOJ1857 傳送帶(三分套三分(難道是傳說中的。。。九分!))

BZOJ1857 傳送帶(三分套三分(難道是傳說中的。。。九分!))

【題目描述】

在一個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

【備註】

對於100%的資料,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000 1<=P,Q,R<=10

【題目分析】

首先%一下用模擬退火和粒子群演算法的大佬(反正我兩個都不會)

然後就是網上大部分的做法:三分套三分。

如果固定一邊,那麼另一邊肯定跑的是一個單峰函式,但如果兩條不定。。。。。我也不會證為什麼三分套三分是對的。。。(能A就靠看題解)直接貼程式碼,感性理解一下。。。。

【程式碼~】

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;

double ax,ay,bx,by,cx,cy,dx,dy,p,q,r;

double dist(double a,double b,double c,double d)
{
	double disx=a-c,disy=b-d;
	return sqrt(disx*disx+disy*disy);
}

double js(double a,double b,double c,double d)
{
	return dist(a,b,c,d)/r+dist(c,d,dx,dy)/q;
}

double sf1(double x,double y)
{ 
    double lx=cx,ly=cy,rx=dx,ry=dy; 
    while(dist(lx,ly,rx,ry)>eps)
	{
        double tmpx=(rx-lx)/3,tmpy=(ry-ly)/3;
        double lmidx=lx+tmpx,rmidx=rx-tmpx,lmidy=ly+tmpy,rmidy=ry-tmpy;
        double ans1=js(x,y,lmidx,lmidy);
		double ans2=js(x,y,rmidx,rmidy); 
        if(ans2-ans1>eps) 
		  rx=rmidx,ry=rmidy;  
        else 
		  lx=lmidx,ly=lmidy; 
    }
    return js(x,y,lx,ly);
}

double sf2()
{
	double lx=ax,ly=ay,rx=bx,ry=by;
	while(dist(lx,ly,rx,ry)>eps)
	{
		double tmpx=(rx-lx)/3,tmpy=(ry-ly)/3;
		double lmidx=lx+tmpx,rmidx=rx-tmpx,lmidy=ly+tmpy,rmidy=ry-tmpy;
		double ans1=sf1(lmidx,lmidy)+dist(ax,ay,lmidx,lmidy)/p;
		double ans2=sf1(rmidx,rmidy)+dist(ax,ay,rmidx,rmidy)/p;
		if(ans2-ans1>eps)
		  rx=rmidx,ry=rmidy;
		else
		  lx=lmidx,ly=lmidy;
	}
	return sf1(lx,ly)+dist(ax,ay,lx,ly)/p;
}

int main()
{
	scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy,&p,&q,&r);
	printf("%.2lf\n",sf2());
	return 0;
}