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;
}

 

posted @ 2018-10-07 21:59  Ishtar~  阅读(115)  评论(0编辑  收藏  举报