有一种和题解区完全不同的做法。
首先将所有任务按照时间从小到大排序,接着用 \(f_i\) 表示处理前 \(i\) 个任务所能得到的最大空闲时间。
回顾一下需要满足的条件:再某个有任务的时刻,如果尼克是空闲的,就必须从中选择一个任务做。那么我们对于第 \(i\) 个任务,枚举上一个做的任务 \(j\),必须满足的条件是:\(j\) 的结束时间 \(+1\sim\) \(i\) 的开始时间 \(-1\) 没有其他任何事件。并且这样做的价值为 \(len_{j 的结束时间 +1\sim i 的开始时间 -1}\)。
这样做的细节也颇多:由于第一个任务不一定是在时刻 \(1\),所以我们得手动设置一个在时刻 \(0\),长度为 \(1\) 的任务,同理需要在设置一个在时刻 \(k+1\) 的任务。
并且为了,满足所有 \(f\) 解出来都是合法的(即不会出现中间有空闲时间但是没做任务的情况),我们先将所有 \(f\) 设置为极小值,再令 \(f_0=0\) 即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline LL read() {
LL sum=0,flag=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') flag=-1; c=getchar();}
while(c>='0'&&c<='9') {sum=sum*10+c-'0'; c=getchar();}
return sum*flag;
}
const int N=1e4+10;
int n,k;
int f[N];
struct node {
int p,t;
}a[N];
int cmp(node x,node y) {
return x.p<y.p;
}
int main() {
// freopen("a.in","r",stdin);
cin>>k>>n;
for(int i=1;i<=n;i++) cin>>a[i].p>>a[i].t;
sort(a+1,a+1+n,cmp);
a[n+1].p=k+1; a[0].t=1;
memset(f,-0x3f,sizeof(f));
f[0]=0;
for(int i=1;i<=n+1;i++) {
int lst=0;
for(int j=i-1;j>=0;j--) {
if(a[j].p+a[j].t-1<a[i].p) {
if(lst) {
if(a[j].p+a[j].t-1>=lst) {
f[i]=max(f[i],f[j]+max(a[i].p-(a[j].p+a[j].t),0));
}
}
else {
f[i]=max(f[i],f[j]+max(a[i].p-(a[j].p+a[j].t),0));
}
}
if(!lst&&a[j].p<a[i].p) lst=a[j].p;
}
}
cout<<f[n+1];
return 0;
}
标签:题解,LL,任务,max,尼克,空闲
From: https://www.cnblogs.com/zhangyuzhe/p/17750410.html