洛谷P4053 [JSOI2007]建筑抢修

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

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

输出格式
输出一个整数S,表示最多可以抢修S个建筑.
输入输出样例
输入 #1复制
4
100 200
200 1300
1000 1250
2000 3200
输出 #1复制
3
添加链接描述

解题思路:
①按建筑的报废时间从小到大排序,最迫切的先修,也就是谁快坏了就先修谁
②请看例子
3
200 200
101 300
201 400
如果只按t2排序我们先修了第一个后,当前时间在200,200+101>300,所以第二个修不了,我们在看第三个,200+201>400,所以第三个也修不了,这样得出的是1,但事实上,应该能修2和3
所以,我们在修了第一个后,判断200+101>300时,我们不该直接放弃这个,都是只能修一个,我们要修2号,不修1号,因为修完2号当前的时间短。

#include
#include
#include
#include
#include
using namespace std;
struct node
{
    int t1;
    int t2;
}a[1500005];
int cmp(struct node z,struct node x)
{
    if(z.t2!=x.t2)
        return z.t2<x.t2;
    else
        return z.t1<x.t1;
}
struct cmp1//队列从大到小排序
{
    bool operator()(int a,int b)
    {
        return a<b;
    }
};
int main()
{
    int n;
    priority_queue<int,vector<int>,cmp1> q;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d %d",&a[i].t1,&a[i].t2);
    }
    sort(a,a+n,cmp);
    int s=0;
    int sum=0;
    for(int i=0;i<n;i++)
    {
        if(sum+a[i].t1>a[i].t2)
        {
            if(a[i].t1<q.top())
            {
                sum=sum-q.top()+a[i].t1;
                q.pop();
                q.push(a[i].t1);
            }
        }
        else
        {
            sum=sum+a[i].t1;
            q.push(a[i].t1);
            s++;
        }
    }
    printf("%d\n",s);
    return 0;
}

你可能感兴趣的:(洛谷,ACM,贪心)