1. 程式人生 > >[BZOJ1857][Scoi2010]傳送帶(三分套三分+計算幾何)

[BZOJ1857][Scoi2010]傳送帶(三分套三分+計算幾何)

題目描述

傳送門

題解

感覺一下好像在傳送帶上走的太多或者走得太少時間都不是最優的
實際上答案對走的長短單峰
然後就三分套三分…
注意:
①find中的ans一定要有初始值,防止根本不進行三分直接退出
②檢查分母不能為0

程式碼

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

const double eps=1e-9;
int dcmp(double
x) { if (x<=eps&&x>=-eps) return 0; return (x>0)?1:-1; } struct Vector { double x,y; Vector(double X=0,double Y=0) { x=X,y=Y; } }; typedef Vector Point; Vector operator + (Vector a,Vector b) {return Vector(a.x+b.x,a.y+b.y);} Vector operator - (Vector a,Vector b) {return
Vector(a.x-b.x,a.y-b.y);} Vector operator * (Vector a,double b) {return Vector(a.x*b,a.y*b);} Point a,b,c,d; double p,q,r,ans; double Dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; } double Len(Vector a) { return sqrt(Dot(a,a)); } double calc(double dis1,double dis2) { Vector v,w; Point e,f; double
dis3,t; v=b-a,w=c-d; if (dcmp(Len(v))) v=v*(dis1/Len(v));e=a+v; if (dcmp(Len(w))) w=w*(dis2/Len(w));f=d+w; dis3=Len(f-e); t=dis1/p+dis2/q+dis3/r; return t; } double find2(double dis) { double l=0,r=Len(d-c),mid1,mid2,ans1,ans2,ans=0; while (dcmp(r-l)>0) { mid1=l+(r-l)/3.0; mid2=r-(r-l)/3.0; ans1=calc(dis,mid1); ans2=calc(dis,mid2); if (dcmp(ans1-ans2)<=0) ans=mid1,r=mid2; else l=mid1; } return calc(dis,ans); } double find1() { double l=0,r=Len(b-a),mid1,mid2,ans1,ans2,ans=0; while (dcmp(r-l)>0) { mid1=l+(r-l)/3.0; mid2=r-(r-l)/3.0; ans1=find2(mid1); ans2=find2(mid2); if (dcmp(ans1-ans2)<=0) ans=mid1,r=mid2; else l=mid1; } return find2(ans); } int main() { scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y); scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y); scanf("%lf%lf%lf",&p,&q,&r); ans=find1(); printf("%.2lf\n",ans); }