建筑抢修(贪心讲题2)
Description
小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者。但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全毁坏。现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。如果某个建筑在一段时间之内没有完全修理完毕,这个建筑就报废了。你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多的建筑。
Input
第一行是一个整数N,接下来N行每行两个整数T1,T2描述一个建筑:修理这个建筑需要T1秒,如果在T2秒之内还没有修理完成,这个建筑就报废了。
Output
输出一个整数S,表示最多可以抢修S个建筑。 数据范围: N<150000,T1
Sample Input
4
100 200
200 1300
1000 1250
2000 3200
100 200
200 1300
1000 1250
2000 3200
Sample Output
3
analyze:
先把所有的建筑的 T2 按照从小到大的顺序排个序,然后再将建筑逐次的“修复”。 “修复”的过程中,我们会遇到这样的状况:修复当前的建筑需要花费的时间加上已经使用了的时间,超过了修复当前建筑的截止时间。 so,如果排在这个建筑前面的已经被修复了的建筑中,有某个建筑的修复时间大于当前这个建筑的修复时间,那么就不修复那个建筑,反而把当前的建筑修复了(取代)。 这会将当前已经使用的时间减少,为后来修复更多的建筑提供了更大的可能。 (可以用Exchange Argument----easily证明)
#include <iostream> #include <cstring> #include <queue> #include <cstdio> #include <algorithm> using namespace std; const int N=150006; struct data { int t1, t2; bool operator < (const data &T) const { return t2<T.t2; } } A[N]; priority_queue <int> Q; int n, ans, cur; int main() { while(scanf("%d", &n)!=EOF) { for(int i=0; i<n; i++) scanf("%d%d", &A[i].t1, &A[i].t2); sort(A, A+n); while(!Q.empty()) Q.pop(); cur=ans=0; for(int i=0; i<n; i++) { if(A[i].t1+cur<=A[i].t2) ans++, Q.push(A[i].t1), cur+=A[i].t1; else { if(Q.empty()) continue; int val=Q.top(); if(val<=A[i].t1) continue; cur-=val-A[i].t1; Q.pop(); Q.push(A[i].t1); } } printf("%d\n", ans); } return 0; }

浙公网安备 33010602011771号