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