校内胡策 埃罗芒阿老师 - 贪心 & 堆 + EX难度 - DP
Posted dprswdr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了校内胡策 埃罗芒阿老师 - 贪心 & 堆 + 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出结果。正解是利用大根堆存储
P.S.: 线段覆盖相当于给出了完整的区间,而该题给出的是可能的范围与区间长度,但具体的区间位置并不确定。
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]); }
以上是关于校内胡策 埃罗芒阿老师 - 贪心 & 堆 + EX难度 - DP的主要内容,如果未能解决你的问题,请参考以下文章