BZOJ 3695 滑行 迭代+二分

来源:互联网 发布:无线路由mac地址修改 编辑:程序博客网 时间:2024/05/04 13:05

题目大意:给定一个n层的区域,从左下角走到右上角,每个区域的高度和速度都不同,问怎么走最快

由于我并不知道光路最速原理所以我写了迭代+二分23333

首先易知每一层的路线都一定是一条直线

我们考虑只有两层的情况 由于左下角和右上角固定 因此我们可以三分确定中间的转折点的位置

或者可以写出时间关于转折点坐标的函数关系 求导之后二分 这个更快一些

那么现在是多层 我们这样搞:

每次迭代,枚举1~n-1的每个转折点,对于第i个转折点确定第i-1个点和第i+1个点的位置,二分确定第i个转折点

这样迭代4000次就能出结果了= = 果断BZ倒数第一

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 110#define EPS 1e-3using namespace std;int n;double X[M],Y[M],v[M];double sqr(double x){return x*x;}double Bisection(int i){double l=X[i-1],r=X[i+1];while(r-l>EPS){double mid=(l+r)/2;double temp=(mid-X[i-1])/sqrt(sqr(mid-X[i-1])+sqr(Y[i]))/v[i]+(mid-X[i+1])/sqrt(sqr(mid-X[i+1])+sqr(Y[i+1]))/v[i+1];if(temp>0)r=mid;elsel=mid;}return (l+r)/2;}int main(){int i,j;cin>>n;cin>>X[n];for(i=1;i<=n;i++)scanf("%lf",&Y[i]);for(i=1;i<=n;i++)scanf("%lf",&v[i]);for(i=1;i<n;i++)X[i]=X[n]/n*i;double delta=0;for(i=1;i<=4000; ++i){delta=0;for(j=1;j<n;j++){double temp=X[j];X[j]=Bisection(j);delta+=fabs(temp-X[j]);}if(delta<EPS)break;}double ans=0;for(i=1;i<=n;i++)ans+=sqrt(sqr(X[i]-X[i-1])+sqr(Y[i]))/v[i];printf("%.3lf\n",ans);return 0;}


0 0
原创粉丝点击