HNOI2001 产品加工

[HNOI2001] 产品加工

题目描述

某加工厂有 A、B 两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成。由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机器共同进行加工,所完成任务又会不同。

某一天,加工厂接到 n 个产品加工的任务,每个任务的工作量不尽一样。

你的任务就是:已知每个任务在 A 机器上加工所需的时间 t1,B 机器上加工所需的时间 t2 及由两台机器共同加工所需的时间 t3,请你合理安排任务的调度顺序,使完成所有 n 个任务的总时间最少。

输入格式

第一行为一个整数 n

接下来 n 行,每行三个非负整数 t1,t2,t3,分别表示第 i 个任务在 A 机器上加工、B 机器上加工、两台机器共同加工所需要的时间。如果所给的时间 t1t20 表示任务不能在该台机器上加工,如果 t30 表示任务不能同时由两台机器加工。

输出格式

仅一行一个整数,表示完成所有 n 个任务的最少总时间。

样例 #1

样例输入 #1

5
2 1 0
0 5 0
2 4 1
0 0 3
2 1 1

样例输出 #1

9

提示

对于所有数据,有 1n6×1030t1,t2,t35

神奇抽象dp题:记dp[i][j]为完成第i个,A最后用时为j,B的最小用时

显然有三种状态转移:
让A做:dp[i-1][j-t1[i]]
让B做:dp[i-1][j]+t2[i]
让AB做 :dp[i-1][j-t3[i]]+t3[i]
``
但是对于125MB的空间限制,我们显然开不出nnk的数组,我们观察状态转移方程可以发现,dp[i]只能从dp[i-1]转移来,我们可以用滚动数组优化掉

但是对于n个物品,最大容量为n5的背包,我们显然不能nn*5转移。我们发现有很多转移到背包是空的,每次转移到时候我们只需要在一个范围[L,R]内进行转移

至于L,R的计算:

对于每次转移:
R+=max(t1,t3)
L+=t1 or t3

Code:

const int N=6005;
const int inf=1e9;
using namespace std;
int dp[N*5],t1[N],t2[N],t3[N];
int n,L,R;
void init()
{
for(int i=0;i<N*5;i++){dp[i]=inf;}
}
void work()
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&t1[i],&t2[i],&t3[i]);
}
init();
dp[0]=0;
for(int i=1;i<=n;i++)
{
R+=max(t1[i],t3[i]);
for(int j=R,A,B,AB;j>=L;j--)
{
A = (t1[i] ? (j-t1[i]>=0 ? dp[j-t1[i]] : inf) : inf);
B = (t2[i] ? dp[j]+t2[i] : inf);
AB= (t3[i] ? (j-t3[i]>=0 ? dp[j-t3[i]]+t3[i] : inf) : inf);
dp[j]=min(AB,min(A,B));
}
L+=(t2[i]|t3[i] ? 0 : t1[i]);
L+=(t1[i]|t2[i] ? 0 : t3[i]);
}
int ans=inf;
for(int i=0;i<=n*5;i++)
{
ans=min(ans,max(i,dp[i]));
}
printf("%d\n",ans);
}
int main()
{
//freopen("P2224.in","r",stdin);freopen("P2224.out","w",stdout);
work();
return 0;
}`
posted @   liuboom  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示