B:Biking Duck
题意:现在有一个人要从(x1,y1)点走到(x2,y2)点, 现在走路的速度为v。 还有骑自行车的速度v2,自行车要从某个自行车站到另一个自行车站,现在我们可以视地图的边界都为自行车站,求最小时间是多少。
题解:对于忽视边界的问题,那就是暴力枚举。现在有了边界, 我们假设一个点在边界,那么我们可以枚举另一个自行车点之后,在某个边界上三分另一个点。 下一个情况就是2个自行车站都在边界上,我们三分套三分去维护找到最小值。
思维不怎么麻烦,就是写的有点麻烦。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<double,double> pll; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL mod = (int)1e9+7; const int N = 1e5 + 100; pll p[N], x, y, ld, ru; double v1, v2; int n; double dis(pll p1, pll p2){ return sqrt(pow(p1.fi-p2.fi,2)+pow(p1.se-p2.se,2)); } double cal(pll p1, pll p2, int fx){ if(fx == 1 || fx == 3){ double posy; if(fx == 1) posy = ld.se; else posy = ru.se; double lx = ld.fi, rx = ru.fi; for(int i = 0; i < 60; ++i){ double m = (lx+rx)/2.0; double mm = (m+rx)/2.0; if((dis(p1,{m,posy})/v2+dis(p2,{m,posy})/v1) > (dis(p1,{mm,posy})/v2+dis(p2,{mm,posy})/v1)) lx = m; else rx = mm; } return dis(p1,{lx,posy})/v2 + dis(p2,{lx,posy})/v1; } else { double posx; if(fx == 2) posx = ld.fi; else posx = ru.fi; double ly = ld.se, ry = ru.se; for(int i = 0; i < 60; ++i){ double m = (ly+ry)/2.0; double mm = (m+ry)/2.0; if(dis(p1,{posx,m})/v2 + dis(p2,{posx,m})/v1 > dis(p1,{posx,mm})/v2 + dis(p2,{posx,mm})/v1) ly = m; else ry = mm; } return dis(p1,{posx,ly})/v2 + dis(p2,{posx,ly})/v1; } } double solve(int fx, int ffx){ if(fx == 1 || fx == 3){ double posy; if(fx == 1) posy = ld.se; else posy = ru.se; double lx = ld.fi, rx = ru.fi; for(int i = 0; i < 60; ++i){ double m = (lx+rx)/2.0; double mm = (m+rx)/2.0; if(dis(x,{m,posy})/v1+cal({m,posy},y,ffx) > dis(x,{mm,posy})/v1+cal({mm,posy},y,ffx)) lx = m; else rx = mm; } return dis(x,{lx,posy})/v1+cal({lx,posy},y,ffx); } else { double posx; if(fx == 2) posx = ld.fi; else posx = ru.fi; double ly = ld.se, ry = ru.se; for(int i = 0; i < 60; ++i){ double m = (ly+ry)/2.0; double mm = (m+ry)/2.0; if(dis(x,{posx,m})/v1+cal({posx,m},y,ffx) > dis(x,{posx,mm})/v1+cal({posx,mm},y,ffx)) ly = m; else ry = mm; } return dis(x,{posx,ly})/v1+cal({posx,ly},y,ffx); } } int main(){ scanf("%lf%lf", &v1, &v2); scanf("%lf%lf", &ld.fi, &ld.se); scanf("%lf%lf", &ru.fi, &ru.se); scanf("%lf%lf", &x.fi, &x.se); scanf("%lf%lf", &y.fi, &y.se); scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%lf%lf", &p[i].fi, &p[i].se); double ans = dis(x,y)/v1; for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j){ double tmp = dis(p[i],p[j])/v2+(dis(p[i],x)+dis(p[j],y))/v1; ans = min(ans, tmp); } for(int i = 1; i <= n; ++i){ ans = min(ans, dis(x,p[i])/v1+cal(p[i],y,1)); ans = min(ans, dis(x,p[i])/v1+cal(p[i],y,2)); ans = min(ans, dis(x,p[i])/v1+cal(p[i],y,3)); ans = min(ans, dis(x,p[i])/v1+cal(p[i],y,4)); ans = min(ans, dis(y,p[i])/v1+cal(p[i],x,1)); ans = min(ans, dis(y,p[i])/v1+cal(p[i],x,2)); ans = min(ans, dis(y,p[i])/v1+cal(p[i],x,3)); ans = min(ans, dis(y,p[i])/v1+cal(p[i],x,4)); } for(int i = 1; i <= 4; ++i){ for(int j = 1; j <= 4; ++j){ ans = min(ans, solve(i,j)); } } printf("%.10f\n", ans); return 0; }