BZOJ 1029 [JSOI2007] 建筑抢修(贪心)

 

题目大意

 

小刚在玩 JSOI 提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T 部落消灭了所有 Z 部落的入侵者。但是 T 部落的基地里已经有 N 个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全毁坏。现在的情况是:T 部落基地里只有 一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。如果某个建筑在一段时间之内没有完全修理完毕,这个建筑就报废了。你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多的建筑。

第一行是一个整数 N,接下来 N 行每行两个整数 T1, T2 描述一个建筑:修理这个建筑需要 T1 秒,如果在 T2 秒之内还没有修理完成,这个建筑就报废了。

输出一个整数 S,表示最多可以抢修 S 个建筑。 数据范围: N<150000,T1

 

做法分析

 

贪心,先把所有的建筑的 T2 按照从小到大的顺序排个序,然后再将建筑逐次的“修复”,“修复”的过程中,我们会遇到这样的状况:修复当前的建筑需要花费的时间加上已经使用了的时间,超过了修复当前建筑的截止时间,如果排在这个建筑前面的已经被修复了的建筑中,有某个建筑的修复时间大于当前这个建筑的修复时间,那么就取代以前修复过的建筑,把当前的建筑修复了,这肯定是会将当前已经使用的时间减少的,为后来修复更多的建筑提供了更大的可能,而要使这个可能性达到最大,那么被取代的建筑的修复时间肯定要最大,由于建筑数量非常多,使用堆优化

 

刚做完这题的时候一时兴起,手写了个堆,满以为时间应该更短才对,结果还是一样的时间...

 

参考代码

 

BZOJ 1029 [JSOI2007] 建筑抢修(贪心)
 1 #include <iostream>

 2 #include <cstring>

 3 #include <queue>

 4 #include <cstdio>

 5 #include <algorithm>

 6 

 7 using namespace std;

 8 

 9 const int N=150006;

10 

11 struct data {

12     int t1, t2;

13     bool operator < (const data &T) const {

14         return t2<T.t2;

15     }

16 } A[N];

17 priority_queue <int> Q;

18 int n, ans, cur;

19 

20 int main() {

21     while(scanf("%d", &n)!=EOF) {

22         for(int i=0; i<n; i++) scanf("%d%d", &A[i].t1, &A[i].t2);

23         sort(A, A+n);

24         while(!Q.empty()) Q.pop();

25         cur=ans=0;

26         for(int i=0; i<n; i++) {

27             if(A[i].t1+cur<=A[i].t2) ans++, Q.push(A[i].t1), cur+=A[i].t1;

28             else {

29                 if(Q.empty()) continue;

30                 int val=Q.top();

31                 if(val<=A[i].t1) continue;

32                 cur-=val-A[i].t1;

33                 Q.pop();

34                 Q.push(A[i].t1);

35             }

36         }

37         printf("%d\n", ans);

38     }

39     return 0;

40 }
优先队列

 

BZOJ 1029 [JSOI2007] 建筑抢修(贪心)
 1 #include <iostream>

 2 #include <cstring>

 3 #include <queue>

 4 #include <cstdio>

 5 #include <algorithm>

 6 

 7 using namespace std;

 8 

 9 const int N=150006;

10 

11 struct Big_Heap {

12     int A[N<<1|1], tot;

13 

14     void init(int n) {

15         for(int i=1; i<=(n<<1|1); i++) A[i]=0;

16         tot=0;

17     }

18 

19     void Insert(int val) {

20         A[++tot]=val;

21         for(int x=tot; x>1 && A[x]>A[x>>1]; x>>=1) swap(A[x], A[x>>1]);

22     }

23 

24     void Update(int val) {

25         A[1]=val;

26         for(int i=1, j=2; j<=tot; i=j, j<<=1) {

27             if((j|1)<=tot && A[j]<A[j|1]) j|=1;

28             if(A[j]<A[i]) break;

29             swap(A[i], A[j]);

30         }

31     }

32 } heap;

33 

34 struct data {

35     int t1, t2;

36     bool operator < (const data &T) const {

37         return t2<T.t2;

38     }

39 } A[N];

40 int n, ans, cur;

41 

42 int main() {

43     while(scanf("%d", &n)!=EOF) {

44         for(int i=0; i<n; i++) scanf("%d%d", &A[i].t1, &A[i].t2);

45         sort(A, A+n);

46         cur=ans=0, heap.init(n);

47         for(int i=0; i<n; i++) {

48             if(A[i].t1+cur<=A[i].t2) ans++, heap.Insert(A[i].t1), cur+=A[i].t1;

49             else {

50                 if(!heap.tot) continue;

51                 int val=heap.A[1];

52                 if(val<=A[i].t1) continue;

53                 cur-=val-A[i].t1;

54                 heap.Update(A[i].t1);

55             }

56         }

57         printf("%d\n", ans);

58     }

59     return 0;

60 }
手写堆

 

题目链接 & AC 通道

 

BZOJ 1029 [JSOI2007] 建筑抢修

 

 

 

你可能感兴趣的:(2007)