BZOJ 1222: [HNOI2001]产品加工【DP】

1222: [HNOI2001]产品加工

Time Limit: 15 Sec Memory Limit: 162 MB

Description

某加工厂有A、B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成。由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机器共同进行加工,所完成任务又会不同。某一天,加工厂接到n个产品加工的任务,每个任务的工作量不尽一样。你的任务就是:已知每个任务在A机器上加工所需的时间t1, B机器上加工所需的时间t2及由两台机器共同加工所需的时间t3,请你合理安排任务的调度顺序,使完成所有n个任务的总时间最少。

Input

输入共n+1行第1行为 n。 n是任务总数(1≤n≤6000)第i+1行为3个[0,5]之间的非负整数t1,t2,t3,分别表示第i个任务在A机器上加工、B机器上加工、两台机器共同加工所需要的时间。如果所给的时间t1或t2为0表示任务不能在该台机器上加工,如果t3为0表示任务不能同时由两台机器加工。

Output

最少完成时间

Sample Input

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

Sample Output

9

题解

这题的想法很不错,我们定义f[j]表示A机器加工了j个时间B机器加工了f[j]个时间,但是我们不知道是否加工完了。为了保证每个都加工过去,那么我们就用背包的原理,每次直接将新的值覆盖上去就可以保证了。
转移方程:
j-t1[i]>=0&&t1[i]>0:New_f[j]=min(New_f[j],f[j-t1[i]]);
t2[i]>0:New_f[j]=min(New_f[j],f[j]+t2[i]);
j-t3[i]>=0&&t3[i]>0:New_f[j]=min(New_f[j],f[j-t3[i]]+t3[i]);
最后取答案:
Ans=min(Ans,max(f[j],j))
应该好理解的吧。

代码如下

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1<<30
using namespace std;
int f[6005*6],n,m;
int main(){
    #ifndef ONLINE_JUDGE
    freopen("prob.in","r",stdin);
    freopen("prob.out","w",stdout);
    #endif
    scanf("%d",&n);m=n*6;
//  memset(f,127,sizeof(f));f[0]=0;
    for(int i=1;i<=n;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        for(int j=m;j>=0;j--){
            int Min=MAXN;
            if(x&&j-x>=0) Min=min(f[j-x],Min);
            if(y) Min=min(f[j]+y,Min);
            if(z&&j-z>=0) Min=min(f[j-z]+z,Min);
            f[j]=Min;
        }
    }
    int Ans=MAXN;
    for(int i=0;i<=m;i++) Ans=min(Ans,max(f[i],i));
    printf("%d",Ans);
    return 0;
}
posted @ 2018-05-12 23:26  XSamsara  阅读(139)  评论(0编辑  收藏  举报