假设要使$A$国获胜,必须要满足$Sum_A>Sum_B+Sum_C$,等价于$Sum_A-Sum_B-Sum_C>0$,不妨求出每个事件的$A[i]-B[i]-C[i]$的值,可以发现该值越大越容易满足$Sum_A-Sum_B-Sum_C$$>0$。那么如果每个事件的该值都$<0$说明最终无法使该国获胜,如果至少存在一个事件使得该值$>0$,那么至少有一个事件满足获胜要求。那么现在想使发生的事件最多,就是让发生的事件尽可能地满足$Sum_A$$-Sum_B-Sum_C$$>0$,而对于每个事件来说,如果$A[i]-B[i]-C[i]>0$,就会使$Sum_A-Sum_B$$-Sum_C>0$更加满足要求,相反,对于$A[i]-B[i]-C[i]<=0$的事件,则会降低$Sum_A-Sum_B$$-Sum_C>0$的可能性。所以,本题的贪心思路是先让$A[i]-B[i]-C[i]>0$的事件进一步满足题目要求,然后再通过$A[i]-B[i]-C[i]<0$的事件去进一步降低满足题目要求的可能性,使其达到临界点为止。这一升一降,不就使发生的事件尽可能多了嘛~
C++代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
LL n, res;
void check(vector<LL> a, vector<LL> b, vector<LL> c)
{
for(int i = 0; i < n; i ++) a[i] -= b[i] + c[i];
sort(a.begin(), a.end()); // 将每个事件作出的贡献值从小到大排序
LL cnt = 0, sum = 0;
// 从后往前遍历,越往后就对Sum_A-Sum_B-Sum_C>0贡献越多,所能发生的事件也就越多
for(int i = n - 1; i >= 0; i --)
{
sum += a[i];
if(sum <= 0) break; // 如果总贡献小于0就停止贡献
cnt ++;
}
if(cnt) res = max(res, cnt);
}
int main()
{
scanf("%lld", &n);
vector<LL> a(n), b(n), c(n); // 使用vector的好处是在通过函数计算时不会修改里面的值
for(int i = 0; i < n; i ++) scanf("%lld", &a[i]);
for(int i = 0; i < n; i ++) scanf("%lld", &b[i]);
for(int i = 0; i < n; i ++) scanf("%lld", &c[i]);
check(a, b, c);
check(b, a, c);
check(c, b, a);
if(!res) puts("-1");
else printf("%d", res);
return 0;
}