网易1:奖学金
小v今年有n门课,每门都有考试,为了拿到奖学金,小v必须让自己的平均成绩至少为avg。每门课由平时成绩和考试成绩组成,满分为r。现在他知道每门课的平时成绩为ai ,若想让这门课的考试成绩多拿一分的话,小v要花bi 的时间复习,不复习的话当然就是0分。同时我们显然可以发现复习得再多也不会拿到超过满分的分数。为了拿到奖学金,小v至少要花多少时间复习。
#include<iostream> #include<vector> #include<algorithm> using namespace std; struct score { int ai;//平时分 int bi;//考试得到一份需付出的努力 }; //以下两种重载<的方法选择其一即可,注意这里不能写<=只能写<或> bool cmp(score &s1, score &s2) { return s1.bi < s2.bi; } bool operator<(const score& s1, const score& s2) { return s1.bi < s2.bi; } void print_vector(vector<score>& ab) { for (int i = 0; i < ab.size(); i++) { cout << ab[i].ai << " " << ab[i].bi << endl; } } /* 贪心算法: 首先将(ai,bi)以bi从小到大排序,然后先取小的bi贡献多余的精力来换取成绩,一直到最后满足成绩即可。 */ int main() { int n, r,avg; /*一定要注意这里:因为它的测试用例是连续输入的,所以必须使整个过程在while循环里. 还有就是注意求和的数定义为long或者long long,否则会越界 */ while(cin>>n>>r>>avg) { int i = 0; long int sumScore = 0;//总的平时分 vector<score> ab(n); while (i < n) { cin >> ab[i].ai >> ab[i].bi; sumScore += ab[i].ai; i++; } //print_vector(ab); //以付出努力大小由小到大排序 sort(ab.begin(), ab.end(),cmp); //print_vector(ab); //当考试成绩小于需要的成绩时,继续循环 long int timeScore = 0, needScore = avg * n - sumScore, spendTime = 0; i = 0; while (timeScore < needScore && i < n) { //若将平时分补齐到10后仍然还不够,则继续努力干,加分 timeScore += r - ab[i].ai; if (timeScore < needScore) { spendTime += (r - ab[i].ai) * ab[i].bi; i++; } else { timeScore -= r - ab[i].ai; spendTime += (needScore - timeScore) * ab[i].bi; break; } } cout << spendTime << endl; } return 0; }