• 题解 P2224 【[HNOI2001]产品加工】


    是道好题,卡常卡到我裂开/kk

    题目链接

    Solution [HNOI2001]产品加工

    题目大意:有两台机器,共(n)个任务,每个任务你可以让第一台机器单独做花费它(a)时间,可以让第二台机器单独做花费它(b)时间,可以让两台机器同时做都花费(c)时间(部分任务有特殊要求,只能某些机器做),求完成所有任务最小时间

    动态规划,奇奇怪怪的优化


    分析:

    首先题意有个不明确的地方(也可能是我没有读出来),就是时间(c)代表两台机器是分工做,而不是同时做,它们互不影响,也就是如果两台机器要共同完成一个任务,并不需要等到两台机器都空闲了,才能一起做

    然后我们发现,当前的状态可以用一个三元组表示出来,((i,a,b))表示已经做了前(i)个任务,第一台机器花费(a)时间,第二台机器花费(b)时间,总时间就是(max(a,b)),三元组的转移十分简单就不在此列出

    空间不允许我们开三维数组,我们可以开二维,把(i,a)丢给下标表示,用数组值来表示(c),因为我们要求最小值,所以只需保存一个(c)最小的三元组即可

    那么(f[i][a])实际上表示已经做了前(i)个任务,第一台机器花费(a)时间的时候第二台机器最少花费的时间

    转移方程:

    [f[i][a]=minegin{cases}f[i-1][a-t_i.a] \ f[i-1][a]+t_i.b \ f[i-1][a-t_i.c]+t[i].cend{cases} ]

    (t_i)表示第(i)个任务,(t_i.a)表示给第一个机器做的时间(其他两个同理),转移条件略去qaq(主要是懒得打

    这个朴素(dp)是跑不过去的,需要亿点点优化

    • 1.滚动数组消去第一维,使空间消耗变得可以接受,并且对连续空间的内存访问可以利用Cache大幅优化常数

    • 2.枚举上下界优化,我们记录一个最小的下界(down),表示(down)是最小的使(f[i][down])状态存在的值。记录一个上界(up),显然(up=sum_{j=1}^i max(t_j.a,t_j.b,t_j.c))

    • 3.边读入边计算,原理同1

    附上不开O2可以勉强卡过的代码:

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    using namespace std;
    const int maxn = 6033,maxm = 33333;
    inline int read(){
    	int x = 0;char c = getchar();
    	while(!isdigit(c))c = getchar();
    	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    	return x; 
    }
    inline int min(int a,int b){return a < b ? a : b;}
    inline int max(int a,int b){return a > b ? a : b;} 
    unsigned short f[maxm];
    int n,ans = 0x7fffffff,down,up;
    int main(){
    	n = read();
    	for(register int i = 1;i <= n;i++){
    		int a = read(),b = read(),c = read(),beg = down;
    		down = 0x7fffffff,up += max(a,max(b,c));
    		for(register int j = up;j >= beg;j--){
    			int tmp = 0x3f3f3f3f;
    			if(a && j - a >= beg)tmp = min(tmp,f[j - a]);
    			if(b)tmp = min(tmp,f[j] + b);
    			if(c && j - c >= beg)tmp = min(tmp,f[j - c] + c);
    			if(tmp < 0x3f3f3f3f)down = min(down,j);
    			f[j] = tmp;
    		}
    	}
    	for(int i = down;i <= up;i++)ans = min(ans,max(i,f[i]));
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    面试题33:把数组排成最小的数
    面试题32:从1到n整数中1出现的次数
    面试题31:连续子数组的最大和
    HTTPS 及加密信息全解析
    面试题30:最小的k个数
    linux退出vi
    linux清除当前屏幕
    java web开发环境配置
    jQuery积累
    html5离线应用详摘
  • 原文地址:https://www.cnblogs.com/colazcy/p/12993023.html
Copyright © 2020-2023  润新知