zoukankan      html  css  js  c++  java
  • [HNOI2001] 产品加工

    题目类型:(DP)

    传送门:>Here<

    题意:有(N)个零件,每个零件有三种选择,在(A)机器加工,在(B)机器加工,同时在(AB)加工。其中所需要的时间分别为(t1[i],t2[i],t3[i])。同一时刻一个机器只能加工一个零件。问加工完所有零件的最少时间

    解题思路

    考虑到有两个进程,以为(dp)会需要(3)维,然而……

    (dp[i][j])表示前(i)个物品加工完毕,其中(A)机器用时(j)时,(B)机器的最小用时。于是每个物品有三种选择,分别转移即可。方程很简单。

    但是这样的做法我们是按照(1,2,...,N)这样的顺序来加工物品的。那么转移的时候显然可能(dp[i][j])不是在(j)的时候发生的,那对于第三种转移不就不合法了吗?

    这里给出一个解释,不知道有没有其他解释方法:我们可以考虑先做所有并行的零件,然后再单独去做。这样的话只能更优不会不优(压掉了空余空间)

    反思

    难就难在(d[i][j])的意义如何去定。其实这还是按照一个确定,一个不确定的思想来定的。当(j)定下来时,影响答案的只有(B)的时间了。我们只要保证(j)尽量小就好了。

    Code

    由于二维会被卡(MLE),因此滚动数组优化。但注意所有(dp[j])不一定都从自身转移过来,因此要重新赋值。但又存在从自己转移过来的可能,所以特殊处理一下。

    /*By DennyQi 2018*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int MAXN = 6010;
    const int INF = 1061109567;
    inline int Max(const int a, const int b){ return (a > b) ? a : b; }
    inline int Min(const int a, const int b){ return (a < b) ? a : b; }
    inline int read(){
        int x = 0; int w = 1; register char c = getchar();
        for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
        if(c == '-') w = -1, c = getchar();
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
    }
    int N,tot_a,tmp;
    int t[4][MAXN],dp[5*MAXN];
    int main(){
    //	freopen(".in","r",stdin);
    	N = read();
    	for(int i = 1; i <= N; ++i){
    		for(int j = 1; j <= 3; ++j){
    			t[j][i] = read();
    		}
    	}
    	memset(dp, 0x3f, sizeof dp);
    	if(t[2][1]){
    		dp[0] = t[2][1];
    	}
    	if(t[1][1]){
    		dp[t[1][1]] = 0;
    	}
    	if(t[3][1]){
    		dp[t[3][1]] = Min(dp[t[3][1]], t[3][1]);
    	}
    	tot_a = Max(t[1][1], t[3][1]);
    	for(int i = 2; i <= N; ++i){
    		tot_a += Max(t[1][i], t[3][i]);
    		for(int j = tot_a; j >= 0; --j){
    			int tmp = dp[j];
    			dp[j] = INF;
    			if(t[2][i]){
    				dp[j] = Min(dp[j], tmp + t[2][i]);
    			}
    			if(t[1][i] && j-t[1][i]>=0){
    				dp[j] = Min(dp[j], dp[j-t[1][i]]);
    			}
    			if(t[3][i] && j-t[3][i]>=0){
    				dp[j] = Min(dp[j], dp[j-t[3][i]] + t[3][i]);
    			}
    //			printf("dp[%d][%d] = %d
    ",i,j,dp[j]);
    		}
    	}
    	int Ans(INF);
    	for(int i = 0; i <= tot_a; ++i){
    		Ans = Min(Ans, Max(i, dp[i]));
    	}
    	printf("%d", Ans);
    	return 0;
    }
    
  • 相关阅读:
    HDU 5528 Count a * b 欧拉函数
    HDU 5534 Partial Tree 完全背包
    HDU 5536 Chip Factory Trie
    HDU 5510 Bazinga KMP
    HDU 4821 String 字符串哈希
    HDU 4814 Golden Radio Base 模拟
    LA 6538 Dinner Coming Soon DP
    HDU 4781 Assignment For Princess 构造
    LA 7056 Colorful Toy Polya定理
    LA 6540 Fibonacci Tree
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9878951.html
Copyright © 2011-2022 走看看