【洛谷P1280】尼克的任务
题目大意:一个人在时间 [1,N] 内工作,现有 M 个任务,每个任务需要在一段固定的时间区间内完成,任务之间的时间可能有重叠。若当前时间有任务要开始,且人处于空闲状态,则一定要这个人来做,否则这个人忽略这个任务。求用以上原则进行工作的最长休息时间是多少。
题解:
若用 f[i] 表示前 i 分钟的最长休息时间的话,发现很难表示出 i 这个点有任务就一定要执行的情况,原因是这是对未来状态的考量。考虑重新设计状态,f[i] 表示从 i 到 N 的最大空闲时间是多少,发现若当前 i 时间有任务要执行,则可以用做完任务的时间转移到当前时间的最优解,就很舒服了。另外,可以用排序优化一下,时间复杂度为 \(O(N+M)\)。
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
int n,m,f[maxn];
struct node{int st,t;}e[maxn];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d%d",&e[i].st,&e[i].t);
sort(e+1,e+m+1,[](const node &x,const node &y){return x.st<y.st;});
for(int i=n,j=m;i>=1;i--){
while(j>=1&&e[j].st>i)--j;
if(j>=1&&e[j].st==i){
while(j>=1&&e[j].st==i)f[i]=max(f[i],f[i+e[j].t]),--j;
}else{
f[i]=f[i+1]+1;
}
}
printf("%d\n",f[1]);
return 0;
}