有n的学员,每个学员有身高 h 和跳跃力 g 两个参数,有一堵高L的墙,若某学员要跳出去,则可以让其他学员搭成塔,满足 没有跳出去的学员(包括该学员)sum(h) + 该学员g >= L,这个学员就可以跳出去。已经跳出去的学员不能回来,通过合理安排学员跳走的顺序,最多能够跳出多少个学员。
首先把每个学员 的 h + g从小到大排序,若某个学员 i 能跳出去,那么就跳出去。当某个学员不能跳出去时,则把已经跳出去的最高的学员 j “叫回来”(其实就是调整一下跳走的顺序), 该学员代替最高的学员跳出去(该学员是一定可以跳出去的,因为hj > hi,且hj + gj < hi + gi),最高的这个学员就不再跳出去了。这个贪心的正确性是因为保证了解不会减少。用一个优先队列即可优化到 O (n log n)。
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef pair<int, int> Data;
#define h first
#define w second
// 优先队列
struct que_cmp {
bool operator() (const Data a, const Data b) {
return a.h < b.h;
}
};
priority_queue <Data, vector<Data>, que_cmp> heap;
int n, h;
#define N 20007
Data d[N];
inline bool sort_cmp(Data a, Data b) {
return a.h + a.w < b.h + b.w;
}
bool Init() {
if (scanf("%d%d\n", &n, &h) == EOF) return false;
for (int i = 0; i < n; i ++)
scanf("%d%d\n", &d[i].h, &d[i].w);
// 排序
sort(d, d + n, sort_cmp);
return true;
}
void Solve() {
while (! heap.empty()) heap.pop();
int res = 0, sum = 0;
// sum是还没有跳出去的学员的高度
for (int i = 0; i < n; i ++) sum += d[i].h;
for (int i = 0; i < n; i ++)
if (sum + d[i].w >= h) {
res ++;
sum -= d[i].h;
heap.push(d[i]);
}
else {
// i学员有可能就是最高的一个
heap.push(d[i]);
sum -= d[i].h;
Data tmp = heap.top();
heap.pop();
sum += tmp.h;
}
printf("%d\n", res);
}
int main() {
freopen("machine.in", "r", stdin);
freopen("machine.out", "w", stdout);
while (Init())
Solve();
return 0;
}