题目大意:这 N
个分身每个都是庄家。你可以到庄家那边下注,每次可以猜大猜小,猜一次一元钱。每一次开彩前,你都可以到任意个庄家那里下赌注。如果开彩结果是大,你就可以得到你之前猜大的庄家相应的
ai元钱。如果开彩结果是小,你就可以得到你之前猜小的庄家相应的
bi元钱。你可以在同一个庄家那里既猜大又猜小(这样是两块钱),也可以什么都不猜(这样不用钱)。想要从它的分身中坑走尽量多的钱。但是会根据你下注的信息控制开彩的结果,让你赢的钱数尽量少。问怎么样下注,才能坑走神仙
czk 最多的钱
这题不难,是个贪心,可是考试时候怎么没有想到呢
题目转化:给定a,b两个序列,每次从a中选定一些数字,b中选定一些数字,其和分别即为
\(sum_a,sum_b\)
取 \[ans=\dfrac
{min(sum_a,sum_b)}{(num_a+num_b)}\]
首先我们给他排个序,一定不会更差
考虑当我们取sumb为答案的时候,也就是suma一定比sumb大的时候的情况,维护双指针,挨个就可以了
然后再考虑取suma为答案的时候,也就是sumb一定比suma大的时候的情况
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <bits/stdc++.h> #define int long long using namespace std;
const int N = 1e5 + 66;
double a[N], b[N], res;
inline bool cmp(double x , double y){return x > y;}
signed main() { int i, n = read(); for (i = 1; i <= n; ++ i) scanf ("%lf%lf", &a[i], &b[i]);
sort(a + 1, a + 1 + n, cmp), sort(b + 1, b + 1 + n, cmp);
double suma(0), sumb(0); int tot(1), num(0); for (i = 1; i <= n; ++ i) { suma += a[i]; ++ num;
while (sumb + b[tot] <= suma && tot <= n) { sumb += b[tot ++]; ++ num; res = max(res, sumb - num); }
if (tot > n) break; res = max(res, sumb - num); }
suma = sumb = 0; tot = 1, num = 0; for (i = 1; i <= n; ++ i) { sumb += b[i]; ++ num; while (suma + a[tot] <= sumb && tot <= n) { suma += a[tot ++]; ++ num; res = max(res, suma - num); }
if (tot > n) break; res = max(res, suma - num); }
printf ("%.4lf", res); return 0; }
|