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 }

 

posted @ 2017-05-08 18:22  Flowersea  阅读(195)  评论(0编辑  收藏  举报