题目描述

牛牛逐渐成长,战斗力也渐渐增加,并可以指挥若干个oier协同作战
给你一个数组a表示我方每个人的战斗力

再给你一个数组b

再给你一个数组c

c[i]表示敌方b[i]战斗力的人有c[i]个

每个oier每次可以选择一名敌方人员进行战斗,如果战斗力大于等于敌方人员,就可以战胜,经验值+1

最开始的时候每个人的经验值都是0

现在牛牛想要打败所有敌方人员,也就是说每个敌方人员都要被一个oier所打败

但是牛牛想要最小化最大的经验值

如果不能打败所有的敌方人员,输出-1

否则输出最小化最大的经验值

输入描述:

第一行输入一个整数n表示我方人员的数量(1 ≤ n ≤ 50)
第二行输入 n个整数ai表示我方每个人员的战斗力(1 ≤ ai ≤ 10000)
第三行输入一个整数m表示b数组的长度(1 ≤ m ≤ 50)
第四行输入m个整数bi (1 ≤ bi ≤ 10000)
第五行输入m个整数ci (1 ≤ ci ≤ 1014)

输出描述:

输出一个整数
思路:先分别用数组和结构体存储我方与敌方的信息,然后对其都进行降序排序(结构体按照敌方战斗力进行降序排序)。
先判断答案为-1的情况,显然只有一种,那就是敌方的最大战斗力>=我方的最大战斗力
然后,因为题目要求输出最小化最大的经验值,即每一个人获得的经验应该尽量平均,公式即为(目前敌方的总人数)/(我方战力高于或等于目前所有敌方的总人数),如果不能整除则+1,并且每一次求出这个值之后都要与当前的最大值比较,取最大值。
至于为什么取最大值,题目中不是要求输出最小化最大的经验值吗?
因为,假设某一次求出值为3,而最大值为2,则表明当前人平均的经验值最小也只能为3,不能再小了,所以取大值3
假设某一次求出值为2,而最大值为3,则虽然表明当前人理论上平均的经验值最小能够到达2,但是请注意,别忘了求出2的时候,总人数>当时求出3时的总人数,这时如果取平均,并且这个平均值小于原来的最大值的时候(大于没关系),相当于把一部分本来只有战力高的那些我方才能获得的经验值给了战力低的我方,相当于如果取2的话,则表明允许战力低的我方获得战力高的敌方的经验了,这与题目中的“如果战斗力大于等于敌方人员,就可以战胜,经验值+1”相违背,所以还是取大值3

代码如下(上面有一位大佬用了lower_bound,如果不用lower_bound的话,用while也可以):
#include<stdio.h>
#include<bits/stdc++.h>
long long int ans=0,sum=0,temp=0;
int a[60];
struct ss {
    int power;  //敌方战力
    long long int num;  //敌方数量
} b[60];
using namespace std;
int cmp1(int a,int b) {
    return a>b;
}
int cmp2(struct ss a,struct ss b) {
    return a.power>b.power;
}
int main() {
    int n,m,i,j=0;
    scanf("%d",&n);
    for(i=0; i<n; i++) scanf("%d",&a[i]);
    scanf("%d",&m);
    for(i=0; i<m; i++) scanf("%d",&b[i].power);
    for(i=0; i<m; i++) scanf("%lld",&b[i].num);
    sort(a,a+n,cmp1);
    sort(b,b+m,cmp2);
    if(b[0].power>a[0]) {
        printf("-1\n");
        return 0;
    }
    for(i=0; i<m; i++) {
        sum+=b[i].num; // sum相当于敌方从b[0].sum一直累加到b[i].sum的总人数
        while(b[i].power<=a[j] && j<n) j++; //j前面初始化为0了,相当于我方战力>=敌方战力的总人数
        if(sum%j==0) temp=sum/j;
        else temp=sum/j+1; //不能整除就+1
        if(ans<temp) ans=temp;
    }
    printf("%lld\n",ans);
    return 0;
}