校内胡策 埃罗芒阿老师 - 贪心 & 堆 + EX难度 - DP

题目描述

埃罗芒阿老师是著名的插画家,她的工作是为电击文库出版的的书画插画。快要到截稿日了,埃罗芒阿老师还在水>_<埃罗芒阿突然发现自己还有一大堆插画没有完成,如果不能在截稿时间内完成是要扣工资的。于是埃罗芒阿老师把每个任务所需的时间和现在(0 时刻)距离每个任务截稿的时间记录了下来,想要计算出最多可以完成多少任务。
输入描述

第一行是一个整数 N,接下来 N 行每行两个整数 T1,T2 描述一个任务:完成这个任务需要 T1 秒,如果在 T2 秒之内还没有完成任务,这个任务就到截稿时间了。
输出描述

输出一个整数 S,表示最多可以完成 S 个任务.
样例输入

4
100 200
200 1300
1000 1250
2000 3200
样例输出

3
数据范围及提示 对于 30%的数据,N≤100;
对于 60%的数据,N≤10000;
对于 80%的数据,N < 150,000; T1 < T2 <
INT_MAX;
对于 100%的数据,N < 150,000; T1 < T2 <
LLONG_MAX;
所有数据保证随机生成。

思路:由于自己是个蒟蒻,第一眼看到还以为是线段覆盖,结果for一遍就WA了。。易发现此题给出的是截至时间和任务时长,而线段覆盖给出的相当于是固定的区间,但此题的任务区间是不固定的,因此不能一遍for出结果。正解是利用大根堆存储

AC Code:

#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int sz=150000+10;
struct node{
    ll t1,t2;
}a[sz];
bool cmp(node a,node b)
{
    if(a.t2==b.t2) return a.t1<b.t1;
    else return a.t2<b.t2;
}
priority_queue<node>q;
bool operator < (node a,node b)
{
    return a.t1<b.t1;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld %lld",&a[i].t1,&a[i].t2);
    }
    sort(a+1,a+n+1,cmp);
    ll ans=0,now=0;
    for(int i=1;i<=n;i++)
    {
        if(now+a[i].t1<=a[i].t2)
        {
            ans++;
            q.push(a[i]);
            now+=a[i].t1;
        } 
        else
        {
            node top=q.top();q.pop();
            now-=top.t1;
            if(top.t1<a[i].t1)
            {
                now+=top.t1;
                q.push(top);
            }
            else
            {
                now+=a[i].t1;
                q.push(a[i]);
            }
        }
    }
    printf("%lld",ans);
    return 0;
}

EX+

有n个任务,在一台机器上完成,机器一次只能做一个任务,第i个任
务需要ti个连续的时刻完成,截止日期在第di个时刻。在截止日期前
完成能得到收益vi。
• 安排顺序,使得收益最大。
• n<=1000,max{di}<=10000。

思路:

 考虑简单情况:当所有任务的截至日期都为m的话,相当于一个体积为m的背包,每个任务相当于一个体积为ti,价值为vi的物品。

再跑一个0/1背包就行了。

又因为截至时间早的一定比截至时间晚的任务先做完。

因此我们将所有任务按截至时间从小到大排序,将背包体积设为最大的截至日期,然后跑0/1背包即可。

注意当 当前体积 即 当前时间 多于当前任务的工作时间 且小于 当前任务的截止日期 时,当前任务才有可能被加入背包。

max = max{d[i]}
for (i=1; i<=n; i++)
  for (j=0; j<=max; j++)
  {
    dp[i][j]=dp[i-1][j];
    if (j>=t[i] && j<=d[i]) dp[i][j]=max(dp[i][j-t[i]]+v[i],dp[i][j]);
  }

猜你喜欢

转载自www.cnblogs.com/Loi-Brilliant/p/8784573.html