1. 程式人生 > >【bzoj1857】傳送帶——三分套三分

【bzoj1857】傳送帶——三分套三分

div get 最優解 ring cal () spl 分享 cst

我的第一道三分題目。 早上跟著cyc學了一下三分,晚上想練一下手發現沒什麽水題就找到了這一道2333 主要是證明是一個單峰函數,這也是本題最難的部分(網上好多人寫出來但不會證明:)) 證明過程來自yyl dalao: 本題要討論必使r<max(q,p),否則還要走什麽傳送帶。。。 從A點出發,要使解最優,必定要走A->E->F->D,其中E是AB上一點,F為CD上一點。 因為E和F都是不確定的,我們不妨假設E點已經確定,那麽CD上必定存在一點F使得EF和FD最優(先不考慮AE),那麽也容易理解,離F點越近的點越優,也就是一個單峰函數啦,可以三分。 那麽再考慮E點,反過來說AB上必定存在一個E使得解最優(不然題目要算什麽),那麽離這個點越近也越優,同樣是單峰,還是三分。 對於AB上三分得到的兩點E1和E2,都有各自在CD上對應的最優點F,此時算出各自的最優解進行比較,所用時間分別為t1,t2,若t1>t2,說明E2離最優解更近,lx=x1,ly=y1;反之則rx=x2,ry=y2。 接著就是三分套三分啦,實現起來不難,具體細節看代碼。 技術分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define eps 1e-3
using namespace std;
struct point 
{
    int x,y;
}a,b,c,d;
int p,q,r;
double dis(double x1,double y1,double x2,double y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double cal(double x,double y) { double lx=c.x,ly=c.y,rx=d.x,ry=d.y; double x1,y1,x2,y2,t1,t2; double ab=dis(x,y,a.x,a.y)/p; while(fabs(rx-lx)>eps||fabs(ry-ly)>eps) { x1=lx+(rx-lx)/3;y1=ly+(ry-ly)/3; x2=lx+(rx-lx)/3*2;y2=ly+(ry-ly)/3*2; t1=ab+dis(x1,y1,x,y)/r+dis(d.x,d.y,x1,y1)/q; t2
=ab+dis(x2,y2,x,y)/r+dis(d.x,d.y,x2,y2)/q; if(t1>t2)lx=x1,ly=y1; else rx=x2,ry=y2; } return ab+dis(lx,ly,x,y)/r+dis(d.x,d.y,lx,ly)/q; } int read() { int x=0,f=1;char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} return x*f; } int main() { a.x=read();a.y=read();b.x=read();b.y=read(); c.x=read();c.y=read();d.x=read();d.y=read(); p=read();q=read();r=read(); double lx=a.x,ly=a.y,rx=b.x,ry=b.y; double x1,y1,x2,y2,t1,t2; while(fabs(rx-lx)>eps||fabs(ry-ly)>eps) { x1=lx+(rx-lx)/3;y1=ly+(ry-ly)/3; x2=lx+(rx-lx)/3*2;y2=ly+(ry-ly)/3*2; t1=cal(x1,y1);t2=cal(x2,y2); if(t1>t2)lx=x1,ly=y1; else rx=x2,ry=y2; } printf("%.2lf",cal(lx,ly)); return 0; }
View Code

【bzoj1857】傳送帶——三分套三分