题意:
一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。
给你一个二维数组 classes ,其中 classes[i] = [passi, totali] ,
表示你提前知道了第 i 个班级总共有 totali 个学生,其中只有 passi 个学生可以通过考试。
给你一个整数 extraStudents ,表示额外有 extraStudents 个聪明的学生,他们 一定 能通过任何班级的期末考。
你需要给这 extraStudents 个学生每人都安排一个班级,使得 所有 班级的 平均 通过率 最大 。
一个班级的 通过率 等于这个班级通过考试的学生人数除以这个班级的总人数。
平均通过率 是所有班级的通过率之和除以班级数目。
请你返回在安排这 extraStudents 个学生去对应班级后的 最大 平均通过率。
与标准答案误差范围在 1e-5 以内的结果都会视为正确结果。
数据范围:
1 <= classes.length <= 1e5
classes[i].length == 2
1 <= passi <= totali <= 1e5
1 <= extraStudents <= 1e5
解法:
因为班级数量是固定的,最大化平均通过率其实就是最大化总通过率.
对于(x,y),加一个学生之后变成(x+1,y+1),通过率的变化量为(x+1)/(y+1)-x/y.
用一个堆存所有二元组(x,y),每次贪心地取出变化量最大的出来即可.
原理是每次添加之后,下一次添加的变化量一定会比这次小,所以每次用堆选出变化量最大的.
code:
struct PI{
int x,y;
bool operator<(const PI &t)const{
double a=(x+1)*1.0/(y+1)-x*1.0/y;
double b=(t.x+1)*1.0/(t.y+1)-t.x*1.0/t.y;
return a<b;
}
};
class Solution {
public:
double maxAverageRatio(vector<vector<int>>& e, int p) {
priority_queue<PI>q;
for(auto i:e){
q.push({i[0],i[1]});
}
while(p--){
PI x=q.top();q.pop();
x.x++,x.y++;
q.push(x);
}
double ans=0;
while(q.size()){
PI x=q.top();q.pop();
ans+=(x.x)*1.0/x.y;
}
ans/=(int)e.size();
return ans;
}
};