[luoguP2224/HNOI2001] 产品加工
题意
有两个进程,每个产品可以在两个进程分别进行或者同时进行,花费时间分别为 \(t1,t2,t3\),求最小可能的时间
sol
典型的将答案写入状态中的 DP。
容易发现,本题的顺序与最终答案无关,因此可以直接按原顺序进行 dp。
考虑暴力状态:设 \(f_{i,j,k}\) 表示前 \(i\) 个产品,第一个进程花费 \(j\) 单位时间,第二个进程花费 \(k\) 单位时间能否做到。这样做的时间复杂度为 \(O(n^3)\)
优化一下,可以得到 \(f_{i,j}\) 表示前 \(i\) 个产品,第一个进程花费 \(j\) 单位时间,第二个进程花费的最小时间,使用滚动数组优化可以保证空间。
对于第二维的枚举,如果直接枚举 \(1 \sim 5i\) 的话,操作数为 \(1.8\times 10^8\),可能会被卡,容易发现,第二维的上界实际上是 \(\sum_{j=1}^i \max \{t1_j,t3_j\}\),动态维护这个上界就不会 TLE 了。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 6005, M = N * 5, INF = 0x3f3f3f3f;
int f[2][M];
int n;
int main(){
    scanf("%d", &n);
    memset(f, 0x3f, sizeof f);
    f[0][0] = 0;
    int up = 0;
    for (int i = 1; i <= n; i ++ ){
        int t1, t2, t3;
        scanf("%d%d%d", &t1, &t2, &t3);
        up += max(t1, t3);
        int o = i & 1, ol = (i - 1) & 1;
        for (int j = 0; j <= up; j ++ ) {
            f[o][j] = INF;
            if (t1 && j >= t1) f[o][j] = min(f[o][j], f[ol][j - t1]);
            if (t2) f[o][j] = min(f[o][j], f[ol][j] + t2);
            if (t3 && j >= t3) f[o][j] = min(f[o][j], f[ol][j - t3] + t3);
        }
    }
    int ans = INF;
    for (int i = 0; i <= up; i ++ ) ans = min(ans, max(i, f[n & 1][i]));
    printf("%d\n", ans);
}

                
            
        
浙公网安备 33010602011771号