[Algo] 贪心策略4
1. 跳跃游戏 II
// 1. 跳跃游戏 II
// https://leetcode.cn/problems/jump-game-ii/
int jump(vector<int>& nums) {
int len = nums.size();
int cur = 0, next = 0, step = 0;
for (int i = 0; i < len; i++) {
if (i > cur) {
step++;
cur = next;
}
next = max(next, i + nums[i]);
}
return step;
}
2. 灌溉花园的最少水龙头数目
// 2. 灌溉花园的最少水龙头数目
// https://leetcode.cn/problems/minimum-number-of-taps-to-open-to-water-a-garden/description/
int minTaps(int n, vector<int>& ranges) {
int n = ranges.size() - 1;
vector<int> right(n + 1);
for (int i = 0; i <= n; i++) {
int start = max(0, i - ranges[i]);
right[start] = max(right[start], i + ranges[i]);
}
int cur = 0, next = 0, ans = 0;
for (int i = 0; i < n; i++) {
next = max(next, right[i]);
if (i == cur) {
if (next > cur) {
ans++;
cur = next;
} else {
return -1;
}
}
}
return ans;
}
3. 超级洗衣机
// 3. 超级洗衣机
// https://leetcode.cn/problems/super-washing-machines/description/
int findMinMoves(vector<int>& machines) {
int len = machines.size(), sum = 0;
for (auto &machine : machines) sum += machine;
if (sum % len != 0) return -1;
int avg = sum / len;
int leftSum = 0, leftNeed, rightSum, rightNeed, cur, ans = 0;
for (int i = 0; i < len; i++) {
rightSum = sum - leftSum - machines[i];
leftNeed = i * avg - leftSum;
rightNeed = (len - i - 1) * avg - rightSum;
if (leftNeed > 0 && rightNeed > 0) cur = leftNeed + rightNeed;
else cur = max(abs(leftNeed), abs(rightNeed));
ans = max(ans, cur);
leftSum += machines[i];
}
return ans;
}
4. 最大平均通过率
// 4. 最大平均通过率
// https://leetcode.cn/problems/maximum-average-pass-ratio/description/
double maxAverageRatio(vector<vector<int>>& classes, int extraStudents) {
int classNum = classes.size();
auto comparator = [](const vector<double> &a, const vector<double> &b) {
return a[2] < b[2];
};
priority_queue<vector<double>, vector<vector<double>>, decltype(comparator)> maxHeap;
for (auto &cLass : classes) {
double pass = (double)cLass[0], total = (double)cLass[1];
double bonus = (pass + 1) / (total + 1) - pass / total;
vector<double> cur = {pass, total, bonus};
maxHeap.push(cur);
}
while (extraStudents-- > 0) {
vector<double> cur = maxHeap.top();
maxHeap.pop();
double newPass = cur[0] + 1, newTotal = cur[1] + 1;
double newBonus = (newPass + 1) / (newTotal + 1) - newPass / newTotal;
vector<double> next = {newPass, newTotal, newBonus};
maxHeap.push(next);
}
double ans = 0;
while (!maxHeap.empty()) {
vector<double> cur = maxHeap.top();
maxHeap.pop();
ans += cur[0] / cur[1];
}
return ans / classNum;
}
5. 雇佣 k 名工人的最低成本
// 5. 雇佣 k 名工人的最低成本
// https://leetcode.cn/problems/minimum-cost-to-hire-k-workers/
double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int k) {
int n = quality.size();
vector<vector<int>> employees(n, vector<int>(2));
for (int i = 0; i < n; i++) {
employees[i][0] = quality[i];
employees[i][1] = wage[i];
}
sort(employees.begin(), employees.end(), [](const vector<int> &a, const vector<int> &b){
return ((double)a[1] / a[0]) < ((double)b[1] / b[0]);
});
int qualitySum = 0;
double ans = 0;
priority_queue<int, vector<int>, less<int>> maxHeap;
for (int i = 0; i < n; i++) {
int curQuality = employees[i][0], curWage = employees[i][1];
double curRatio = (double)curWage / curQuality;
if (maxHeap.size() < k) {
qualitySum += curQuality;
maxHeap.push(curQuality);
if (maxHeap.size() == k) {
ans = qualitySum * curRatio;
}
} else {
if (curQuality < maxHeap.top()) {
qualitySum += curQuality - maxHeap.top();
maxHeap.pop();
maxHeap.push(curQuality);
ans = min(ans, qualitySum * curRatio);
}
}
}
return ans;
}