Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) D. Dynamic Problem Scoring 贪心
链接:
http://codeforces.com/contest/807/problem/D
题意:
一场比赛一共5道题,有n个参赛者,现在只关心前两个,要使第一个人最后得分比第二个人高
每道题的总分数和通过这道题的人数与总人数的比值有关,如下表
现在给出每个人的每道题的通过时间,如果没有通过,时间为-1
通过的题的的分数为这道题的总分数*(1-通过时间/250)。
现在A(第一个人)想要超过第二个人(B),A有很多小号,问你A最小需要开几个小号才能超过B,或者永远也超不过
题解:
这道题的N最大为120,现在考虑极端的例子,假设有N个人,全都通过了这道题,如果想让通过率变为最小的,也就是1/32,那么最多也只需要开32倍的小号(或者33倍?)
反之,如果通过率为0想变成1/2 也是32倍的N,所以这道题可以暴力枚举开小号的个数,然后在贪心决定这些小号在每道题上通过与否
假如A没通过这道题,那么小号自然也通过不了
假如A过了这道题,B没过,那么肯定要让这道题的通过率低,所以开的小号都不通过这道题
假如A和B都过了,但是A比B快,还是小号全都不通过
这样就只有A和B都通过了,B比A快的时候,才让小号全都通过这道题,这样这道题通过率就上升了,分数就下降了
代码:
31 int n; 32 int a[120][5], cnt[5]; 33 34 int cal(int id, int pid, int num) { 35 if (a[id][pid] == -1) return 0; 36 int maxPoint = 500, solved; 37 if (a[0][pid] == -1 || a[1][pid] == -1 || a[0][pid] < a[1][pid]) 38 solved = cnt[pid]; 39 else solved = cnt[pid] + num - n; 40 for (int i = 2; i <= 32; i *= 2) { 41 if (solved*i > num) break; 42 maxPoint += 500; 43 } 44 return maxPoint*(1 - a[id][pid] / 250.0); 45 } 46 47 int main() { 48 cin >> n; 49 rep(i, 0, n) rep(j, 0, 5) { 50 cin >> a[i][j]; 51 if (a[i][j] != -1) cnt[j]++; 52 } 53 rep(num, n, 40 * n) { 54 int A = 0, B = 0; 55 rep(j, 0, 5) A += cal(0, j, num); 56 rep(j, 0, 5) B += cal(1, j, num); 57 if (A > B) { 58 cout << num - n << endl; 59 return 0; 60 } 61 } 62 cout << -1 << endl; 63 return 0; 64 }