您的位置:首页 > 其它

bzoj1857 传送带 三分

2016-01-05 20:57 239 查看
很早看到的三分法,竟然在今天用到了(显然已我的智商是想不到的)。然而发现自己并不会证明o(╯□╰)o,但是除了最关键的一步其它还是会的>_<。

首先,我们用三分法,最基本的是要证明那个人一定是沿着如下路径走的:从A沿着AB走一段,再穿越到CD上某一点,最后到终点。证明如下:不妨假设p>q>r,因为当r>max(p,q)时没什么好讨论的,而p,q的大小没什么关系。那么假设这人从AB上一点X离开,那么如果它不沿着刚刚的路径,则它一定会沿着某个路径回到AB上一点Y,显然X->Y的最快方法是沿着AB走,因为这样距离最短而速度最快。证完。

那么,如果我们假设它从AB上一点X出发到CD上一点Y再到终点,那么当X为定点时,时间与CY长度是成单峰函数的,证明如下:



当s>=q时,显然时间随着CY的增大而减小,显然是单峰函数,因此不妨设s<q。过点X作XH⊥CD,显然当Y在CH上时时间增大,不做讨论。当Y在HD上时,设XH=h,HY=t,那么Y点比D点的时间节约(当Y点比D点时间长时该式为负号):t/q-(sqrt(t^2+h^2)-h)/s=t/q+h/s-sqrt(t^2+h^2)/s,显然sqrt(t^2+h^2)增长是没有t的增长快的,因此一开始该式为正数,时间减少;但是当t增大时,sqrt(t^2+h^2)的增大速度不断变快最终趋向于t的增大速度,不要忘了q>s,所以该式最终会变为负数并且一定会越变越小,时间不断增大。综上所述:时间先单调递减再单调递增,证完。

然而我并不会证明从AB上一点X离开的最优时间,这个函数与AX成单峰函数关系。。。算了先挖个坑,谁会请告诉我>_<。AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define eps 1e-3
using namespace std;

int ax,bx,cx,dx,ay,by,cy,dy,p,q,r;
double dist(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double solve(double u,double v){
double lx=cx,ly=cy,rx=dx,ry=dy,x1,x2,y1,y2,t1,t2;
while (abs(lx-rx)>eps || abs(ly-ry)>eps){
x1=(lx+lx+rx)/3; x2=(x1+rx)/2; y1=(ly+ly+ry)/3; y2=(y1+ry)/2;
t1=dist(x1,y1,dx,dy)/q+dist(x1,y1,u,v)/r;
t2=dist(x2,y2,dx,dy)/q+dist(x2,y2,u,v)/r;
if (t1<t2){ rx=x2; ry=y2; } else{ lx=x1; ly=y1; }
}
return dist(ax,ay,u,v)/p+dist(lx,ly,dx,dy)/q+dist(lx,ly,u,v)/r;
}
int main(){
scanf("%d%d%d%d%d%d%d%d",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy);
scanf("%d%d%d",&p,&q,&r);
double lx=ax,ly=ay,rx=bx,ry=by,x1,x2,y1,y2;
while (abs(lx-rx)>eps || abs(ly-ry)>eps){
x1=(lx+lx+rx)/3; x2=(x1+rx)/2; y1=(ly+ly+ry)/3; y2=(y1+ry)/2;
if (solve(x1,y1)<solve(x2,y2)){ rx=x2; ry=y2; } else{ lx=x1; ly=y1; }
}
printf("%.2f\n",solve(lx,ly));
return 0;
}


by lych

2016.1.5
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: