尼克的任务——线性dp
P1280 尼克的任务 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
一道线性dp的基础题。但是状态方程自己想复杂了。刚开始是想用二维数组表示,选择i项工作后时间到j的总工作时长最小是多少,然后用总时间减它。很麻烦,而且不会写.。。。然后看了题解,发现只需要一维数组即可。状态表示是从第i分起开始工作的最大摸鱼时间。
问题:为什么状态方程不是从第1分钟开始到第i分钟结束的最大摸鱼时间呢?
因为这样思考量太大了,还要考虑前几项工作的最终时长什么的。所以正难则反,我们的状态方程设为i分钟是起点。
状态计算:
1.如果i时刻没有工作刚开始,那么f[i]=f[i+1]+1 (摸鱼一分钟)
2.如果i时刻有工作要刚开始,那么就在所有i时刻开始的工作中遍历,求最大的摸鱼时长。
f[i]=max(f[i],f[i+num[i][j])
答案所求即为f [ 1 ]
小技巧:用vector记录每项工作开始时间对应的结束时间,没必要记录每项工作的序号。

1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=1e4+100; 4 vector<int>num[N]; 5 int n,k,p,t,f[N]; 6 7 int main() 8 { 9 scanf("%d%d",&n,&k); 10 for(int i=1;i<=k;i++) 11 { 12 scanf("%d%d",&p,&t); 13 num[p].push_back(t); 14 } 15 16 for(int i=n;i;i--) 17 { 18 if(num[i].empty())f[i]=f[i+1]+1; 19 else 20 { 21 for(int j=0;j<num[i].size();j++) 22 f[i]=max(f[i],f[i+num[i][j]]); 23 } 24 } 25 26 printf("%d\n",f[1]); 27 28 29 30 return 0; 31 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现