【SRM543 Div2 1000】 EllysThreeRivers

记几个前一段遇到的几个比较好玩的题目,以后再来回味~~

  

题目链接

在Div1各种被虐,就开小号做Div2,遇到了这么一个题,题目意思很简单:

一个矩形区域竖直分为3部分,三条不同的河流,一个人从左下角游到右上角,在三条河中的速度不同v1,v2,v3,还有一个v是竖直沿河走的速度,问最小时间。

看到这个题目直接就想到了以前我出过的一个题目:忽略河的宽度的一个过河问题,出题时和Su_xing大神讨论到当考虑河宽度的时候可以根据一个定理来搞,也就是费马原理

费马原理指出光在任意介质中从一点传播到另一点时,沿所需时间最短的路径传播。而这里我们要求最短路径,那么就可以依据光的折射法则。当时只提了一下猜想,也没去多想。这题不就是为这个定理而出的么,只要三分枚举第一次走时的角度,后面两条河走的角度都可以通过光线折射的方法去推出,然后竖直走到终点,取最小值就可以了。

 1 #include <cstdlib> 
 2 #include <cctype> 
 3 #include <cstring> 
 4 #include <cstdio> 
 5 #include <cmath> 
 6 #include <algorithm> 
 7 #include <vector> 
 8 #include <string> 
 9 #include <iostream> 
10 #include <sstream> 
11 #include <map> 
12 #include <set> 
13 #include <queue> 
14 #include <stack> 
15 #include <fstream> 
16 #include <numeric> 
17 #include <iomanip> 
18 #include <bitset> 
19 using namespace std; 
20 #define MIN(x,y) (x>y?y:x) 
21 #define MAX(x,y) (x<y?y:x) 
22 #define ABS(x) (x>0?x:(-x)) 
23 #define PI (acos(-1)) 
24 
25 class EllysThreeRivers 
26 { 
27 public: 
28   int l, wv; 
29   vector<int> wl; 
30   vector<int> sv; 
31    
32   double get(double r){ 
33     double h = 0, t = 0; 
34     h += double(wl[0])*tan(r); 
35     t += double(wl[0])/cos(r)/double(sv[0]); 
36     r = asin(double(sv[1])/double(sv[0])*sin(r)); 
37     h += double(wl[1])*tan(r); 
38     t += double(wl[1])/cos(r)/double(sv[1]); 
39     r = asin(double(sv[2])/double(sv[1])*sin(r)); 
40     h += double(wl[2])*tan(r); 
41     t += double(wl[2])/cos(r)/double(sv[2]); 
42     t += fabs(double(l)-h)/(double)wv; 
43     return t; 
44   } 
45 
46   double getMin(int length, int walk, vector <int> width, vector <int> swim){ 
47     l = length; 
48     wv = walk; 
49     wl = width; 
50     sv = swim; 
51      
52     double l = 0, r = PI/2.0; 
53     double ll = (l*2.0+r)/3.0; 
54     double rr = (l+r*2.0)/3.0; 
55     while(rr-ll>1e-12){ 
56       double lt = get(ll); 
57       double rt = get(rr); 
58       if(lt>=rt){ 
59         l = ll; 
60       }else{ 
61         r = rr; 
62       } 
63       ll = (l*2.0+r)/3.0; 
64       rr = (l+r*2.0)/3.0; 
65     } 
66     return get(rr); 
67   } 
68 }; 

可惜比赛时候脑残了,精度开小了 STF,赛后改了下精度就过了T-T

Div1的500不是这题,而是有多条河,只能走整数点的情况,貌似是一个要优化的DP题。

 

posted @ 2012-07-02 19:52  Amb@HDU  阅读(322)  评论(0编辑  收藏  举报