题意:有$n$个小学生需要到距离为$l$的地方去,步行的速度是$v_1$,它们租了一辆大巴,速度是$v_2$,大巴上最多容纳$k$个乘客,每个小学生最多乘车一次,初始时大巴和小学生都在起点,问至少需要多长时间所有小学生都可以到达终点。时间精确到$10^{-6}$。数据范围$1 \leq l \leq 1e9, 1 \leq v_1 < v_2 \leq 1e9, 1 \leq k \leq n$。
分析:你可能会想到用大巴把小学生送到终点再折回,如此反复,直到最后一次不折回。但是样例$2$提示我们这种贪心不是最优的,大巴不一定要把小学生送到终点,因此考虑二分时间,那么假设时间$t$内可以完成目标,可以导出每个小学生的乘车距离最少是$\frac{v_2(l-v_1t)}{v_2-v_1}$,并且大巴需要折回至少$\frac{n}{ k }- [n \mod k = 0]$次,于是根据这两个信息得出最小花费时间与$t$作比较即可完成二分。代码如下:
1 #include <algorithm> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <queue> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <ctime> 10 #include <cmath> 11 #include <iostream> 12 #include <assert.h> 13 #pragma comment(linker, "/STACK:102400000,102400000") 14 #define max(a, b) ((a) > (b) ? (a) : (b)) 15 #define min(a, b) ((a) < (b) ? (a) : (b)) 16 #define mp std :: make_pair 17 #define st first 18 #define nd second 19 #define keyn (root->ch[1]->ch[0]) 20 #define lson (u << 1) 21 #define rson (u << 1 | 1) 22 #define pii std :: pair<int, int> 23 #define pll pair<ll, ll> 24 #define pb push_back 25 #define type(x) __typeof(x.begin()) 26 #define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++) 27 #define FOR(i, s, t) for(int i = (s); i <= (t); i++) 28 #define ROF(i, t, s) for(int i = (t); i >= (s); i--) 29 #define dbg(x) std::cout << x << std::endl 30 #define dbg2(x, y) std::cout << x << " " << y << std::endl 31 #define clr(x, i) memset(x, (i), sizeof(x)) 32 #define maximize(x, y) x = max((x), (y)) 33 #define minimize(x, y) x = min((x), (y)) 34 using namespace std; 35 typedef long long ll; 36 const int int_inf = 0x3f3f3f3f; 37 const ll ll_inf = 0x3f3f3f3f3f3f3f3f; 38 const int INT_INF = (int)((1ll << 31) - 1); 39 const double double_inf = 1e30; 40 const double eps = 1e-14; 41 typedef unsigned long long ul; 42 typedef unsigned int ui; 43 inline int readint(){ 44 int x; 45 scanf("%d", &x); 46 return x; 47 } 48 inline int readstr(char *s){ 49 scanf("%s", s); 50 return strlen(s); 51 } 52 53 class cmpt{ 54 public: 55 bool operator () (const int &x, const int &y) const{ 56 return x > y; 57 } 58 }; 59 60 int Rand(int x, int o){ 61 //if o set, return [1, x], else return [0, x - 1] 62 if(!x) return 0; 63 int tem = (int)((double)rand() / RAND_MAX * x) % x; 64 return o ? tem + 1 : tem; 65 } 66 ll ll_rand(ll x, int o){ 67 if(!x) return 0; 68 ll tem = (ll)((double)rand() / RAND_MAX * x) % x; 69 return o ? tem + 1 : tem; 70 } 71 72 void data_gen(){ 73 srand(time(0)); 74 freopen("in.txt", "w", stdout); 75 int kases = 40000; 76 printf("%d\n", kases); 77 while(kases--){ 78 ll sz = 1e18; 79 printf("%lld\n", Rand(sz, 1)); 80 } 81 } 82 83 struct cmpx{ 84 bool operator () (int x, int y) { return x > y; } 85 }; 86 double power(double a, int p){ 87 double ans = 1.; 88 while(p){ 89 if(p & 1) ans *= a; 90 p >>= 1; 91 a = a * a; 92 } 93 return ans; 94 } 95 int main(){ 96 //data_gen(); return 0; 97 //C(); return 0; 98 int debug = 0; 99 if(debug) freopen("in.txt", "r", stdin); 100 //freopen("out.txt", "w", stdout); 101 int n, l, v1, v2, k; 102 while(~scanf("%d", &n)){ 103 l = readint(), v1 = readint(), v2 = readint(), k = readint(); 104 int lamda = n / k - (n % k == 0); 105 double L = (double)l / v2, R = (double)l / v1; 106 while(R - L > 1e-6){ 107 //printf("%.10f %.10f\n", L, R); 108 //printf("err is %.10f\n", R - L); 109 double mid = (L + R) / 2; 110 //printf("mid is %.10f\n", mid); 111 double d = (double)v2 * (l - v1 * mid) / (v2 - v1); 112 double lhs = 2. * d * v1 * lamda / (v1 + v2) + d; 113 int ok = 1; 114 if(lhs >= l) ok = 0; 115 if(ok){ 116 double rhs = 2. * d * lamda / (v1 + v2); 117 rhs += (l - lhs + d) / v2; 118 if(rhs > mid) ok = 0; 119 } 120 if(ok) R = mid; 121 else L = mid; 122 } 123 //if(n % k) ans += d / v2; 124 printf("%.10f\n", L); 125 } 126 return 0; 127 }
code:
这里还需要注意二分的精度不能太高,否则可能由于浮点误差跳不出循环。
时间: 2024-11-08 23:20:57