“一切都会好起来的。”|

zplqwq

园龄:3年10个月粉丝:25关注:14

📂题解
🔖DP
2022-10-20 11:49阅读: 27评论: 0推荐: 0

题解 P2224 [HNOI2001]产品加工

一道很有趣的 dp 题。

这道题是以答案为下标来设定状态,在这种生产问题这个套路还是挺常见的,需要积累一下。

我们令 fi,j 为前 i 个任务 A 机器花了j 时间的时候,B 机器花费的时间最少是多少。

所以答案就是 min{max{i,fn,i}} 。我们对于每一个时间 i 所需要的总时间就是做完前 n 个任务 B 花费的时间和 A 花费的时间的最大值。由于我们枚举的 i 就是 A 花费的时间,所以只需与 fn,i 取最大值即可。

转移可以考虑从三个方向转移过来,对于当前任务,我们分别考虑是 A 做,B 做,还是 AB 一起做。

即可以推出转移方程。

fi,j=max{fi1,jt1ifi1,j+t2ifi1,jt3i+t3i

我们发现这样的空间开销是很大的,因为我们既要记录是哪个任务还要记录时间。

我们发现对于第 i 个任务只能从 i1 这个任务转移过来,所以可以滚动数组。

还有一个关于枚举的时间的优化。不难发现,对于当前任务 i 的时间 jj 一定不会超过前 i1 个任务所花的时间的最大值。

jmax(t1i,t2i,t3i)

细节不算多,但注意数组开大点,因为时间的大小比较玄学。

#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 中国大陆许可协议进行许可。

posted @   zplqwq  阅读(27)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示