HNOI2001 产品加工
[HNOI2001] 产品加工
题目描述
某加工厂有 A、B 两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成。由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机器共同进行加工,所完成任务又会不同。
某一天,加工厂接到
你的任务就是:已知每个任务在 A 机器上加工所需的时间
输入格式
第一行为一个整数
接下来
输出格式
仅一行一个整数,表示完成所有
样例 #1
样例输入 #1
5 2 1 0 0 5 0 2 4 1 0 0 3 2 1 1
样例输出 #1
9
提示
对于所有数据,有
神奇抽象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; }`