题目链接:https://www.luogu.com.cn/problem/P1280
分析:
DP的状态表示的第一个念头就是我们题目求的是什么,我们就表示什么。
1.如果正序来进行求解的话,定义f[i]为1~i时间段内能够休息的最大时间。那么我们会发现,前面的选择情况对后面是有影响的。比如a[i]这个点有多个工作,那么我们选择的任何一种工作对未来都会存在影响,而这就不满足动态规划的无后效性了。所谓的无后效性,即对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策。
2.而如果通过逆序的方式进行求解的话,f[i]定义为:i ~ n时间段内能够休息的最大时间。所以我们会通过f[i]去推f[i - 1],从而i以及其i后面的阶段,是否进行工作,对f[i - 1]没有影响。
状态计算:如果i不存在任务:f[i] = f[i + 1] + 1;
如果i存在任务,则遍历这些任务找到对应的最大值。f[i] = max(f[i], f[i + len]);
代码实现:
# include <iostream>
# include <algorithm>
using namespace std;
const int N = 1e4 + 10;
int f[N];
pair<int,int> q[N];
int n,k;
bool cmp(pair<int,int> q1 , pair<int,int> q2)
{
return q1.first > q2.first;
}
int main()
{
scanf("%d %d",&n,&k);
for(int i = 1 ; i <= k ; i++)
{
scanf("%d %d",&q[i].first,&q[i].second);
}
sort(q + 1 , q + 1 + k , cmp);
//求的是最大值,而初始情况下都为0。
for(int i = n , j = 1; i >= 1 ; i--)
{
bool flag = false;
while(j <= k && q[j].first == i)
{
flag = true;
f[i] = max(f[i],f[ i + q[j].second]);
j++;
}
if(!flag) // 可以休息
{
f[i] = f[i + 1] + 1;
}
}
printf("%d\n",f[1]);
return 0;
}