P1280 尼克的任务 线性dp
其实看到这道题第一眼看成了贪心
其实是个很奇怪的线性dp
dp[i]代表在i到n时间内的最长休息时间
先放状态转移方程这里的list[num].t是指第num个工作的起始时间
由题意可知 只有空闲时间有任务开始 才会去做
所以我们枚举每个这段时间的任务 看那个能够获得最长的休息时间但是要注意 这里循环要倒着跑 因为dp[i]=dp[i+1]+1; 如果顺着跑 在跑到dp[i]时 很显然dp[i+1]还没有转移过知道了思路 放代码
dp[i] = max(dp[i],dp[i+list[num].t]);//如果此刻有任务 dp[i] = dp[i+1]+1;//如果此刻没任务
#define rep(i,a,b) for(int i=a;i<=b;i++)
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int e = (int)1e5+5;
struct node
{
int p;
int t;
}list[e];
bool cmp(node a,node b){
return a.p>b.p;
}
int num=1;
int dp[e],sum[e];
int n,k;
int main(int argc, char const *argv[])
{
cin >> n >> k;
rep(i,1,k){
cin >> list[i].p >> list[i].t;
sum[list[i].p]++;
}
sort(list+1,list+1+k,cmp);
for(int i = n;i >= 1;i--){
if(!sum[i]){
dp[i] = dp[i+1]+1;
}
else
for(int j = 1;j <= sum[i]; j++){
dp[i] = max(dp[i],dp[i+list[num].t]);
num++;
}
}
printf("%d
",dp[1]);
return 0;
}