题目
思路
乱搞出来的。。。
之前被卡了一上午。。现在突然十几分钟做出来,感觉有点梦幻,我还以为它有多难。。
大体来说,就是很简单的线性DP,两个转移:
1.当当前没有工作开头的时候,空余时间+1,并转移到下一分钟。
2.当当前有工作开头的时候,选择其中的一个工作,并转移到这个工作结束的时间。
本题用记忆话搜索递归比较容易,反正和递推顶死差在一个量级里面。
复杂度什么的以后自己看总结。。现在对这道题还迷糊着呢。。
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;
const int maxn = 10000 + 10;
struct node {
int s, e;
bool operator < (const struct node& rhs) const {
return s < rhs.s;
}
}tasks[maxn];
int N, K, d[maxn];
int dp(int T) {
if (T > N) return 0;
int &ans = d[T];
if (ans != -1) return ans;
ans = 0;
node no;
no.s = T;
node* np = lower_bound(tasks + 1, tasks + 1 + K, no);
if (np->s == T) {
while (np->s == T) {
ans = max(ans, dp(np->e));
np++;
}
}
else {
ans = dp(T + 1) + 1;
}
return ans;
}
int main() {
scanf("%d%d", &N, &K);
int s, c;
_rep(i, 1, K) {
scanf("%d%d", &s, &c);
tasks[i].s = s;
tasks[i].e = s + c;
}
sort(tasks + 1, tasks + 1 + K);
memset(d, -1, sizeof(d));
int ans = dp(1);
printf("%d\n", ans);
return 0;
}
/*
如果这道题做出来的话,可以证明:
在题都想不出来咋做的时候,递归永远比递推容易想出来。。
*/