题解 P2224 [HNOI2001]产品加工
一道很有趣的 dp 题。
这道题是以答案为下标来设定状态,在这种生产问题这个套路还是挺常见的,需要积累一下。
我们令 为前 个任务 机器花了 时间的时候, 机器花费的时间最少是多少。
所以答案就是 。我们对于每一个时间 所需要的总时间就是做完前 个任务 花费的时间和 花费的时间的最大值。由于我们枚举的 就是 花费的时间,所以只需与 取最大值即可。
转移可以考虑从三个方向转移过来,对于当前任务,我们分别考虑是 做, 做,还是 和 一起做。
即可以推出转移方程。
我们发现这样的空间开销是很大的,因为我们既要记录是哪个任务还要记录时间。
我们发现对于第 个任务只能从 这个任务转移过来,所以可以滚动数组。
还有一个关于枚举的时间的优化。不难发现,对于当前任务 的时间 , 一定不会超过前 个任务所花的时间的最大值。
即 。
细节不算多,但注意数组开大点,因为时间的大小比较玄学。
#include<bits/stdc++.h> using namespace std; #define int long long const int N=3e4+10; int t1[N],t2[N],t3[N]; int n; int dp[10][N]; signed main() { cin>>n; for(int i=1;i<=n;i++) { cin>>t1[i]>>t2[i]>>t3[i]; } int sum=0; memset(dp,0x3f,sizeof(dp)); dp[0][0]=0; for(int i=1;i<=n;i++) { sum+=max(t1[i],t3[i]); memset(dp[i&1],0x3f,sizeof(dp[i&1])); for(int j=0;j<=sum;j++) { if(t2[i]!=0) dp[i&1][j]=min(dp[(i&1)^1][j]+t2[i],dp[i&1][j]); if(t1[i]!=0 and j-t1[i]>=0) dp[i&1][j]=min(dp[i&1][j],dp[(i&1)^1][j-t1[i]]); if(t3[i]!=0 and j-t3[i]>=0) dp[i&1][j]=min(dp[i&1][j],dp[(i&1)^1][j-t3[i]]+t3[i]); } } int ans=0x7fffffff; for(int i=0;i<=sum;i++) { ans=min(ans,max(i,dp[n&1][i])); } cout<<ans; return 0; }
本文作者:zplqwq
本文链接:https://www.cnblogs.com/zplqwq/p/16809340.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步