当前位置: 首页 > 工具软件 > Rye > 使用案例 >

ICPCCamp2017 Day 4 A The Catcher in the Rye(二分+光的折射定律)

阙弘博
2023-12-01

大体题意:

告诉你有三个矩形连在一起,要求你从第一个矩形左下角出发,到第三个矩形的右上角,在每个矩形中速度不一样,求最少时间?

思路:

最容易想到的是三分。

取第一个矩形的走的高度是x, 第二个玻璃走的高度是y,列一个函数发现是一个凹函数。

三分就好了。但是时间是0.25s  过不了。

不过有大神 有一个小技巧,就是把这三个矩形 缩小h倍。  最后算完 在乘回去。  (好猛= =)


其实正解是二分。 

把它想成光线, 肯定有一个唯一确定的光线路径。

利用光的折射定律来二分。

只需要二分枚举第一个路径的角度, 就可以算出剩下的两个来,加起来看是否是高度H即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define sqr(x) ((x)*(x))
using namespace std;
const double eps = 1e-10;
const double pi = acos(-1.0);
int T;
double h,a,b,c,va,vb,vc;
int mm = 16;
double oo = 1e5+10;
inline int dcmp(double a,double b){
    if (fabs(a-b) < eps) return 0;
    if (a < b) return -1;
    return 1;
}
double ha,hb,hc;
void go(double m){
    double sina = sin(m);
    double cosa = sqrt(1-sqr(sina));
    double tana = sina/cosa;
    ha = tana*a;
    double sinb = sina*vb/va;
    double cosb = sqrt(1-sqr(sinb));
    double tanb = sinb/cosb;
    hb = b*tanb;
    double sinc = sina*vc/va;
    double cosc = sqrt(1-sqr(sinc));
    double tanc = sinc/cosc;
    hc = c*tanc;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%lf %lf %lf %lf %lf %lf %lf",&h, &a, &b, &c, &va, &vb, &vc);
        double l = 0, r = pi/2;
        while(r-l > eps){
            double m = (l+r)/2;
            go(m);
            if (dcmp(ha+hb+hc,h) < 0) l=m;
            else r = m;
        }
        go((l+r)/2);
        printf("%.10f\n",sqrt(sqr(ha)+sqr(a))/va + sqrt(sqr(hb)+sqr(b))/vb + sqrt(sqr(hc)+sqr(c))/vc);
    }
    return 0;
}
/**
2
10 3 4 3 1 1 1
21 5 12 4 4 3 4

**/



 类似资料: