USACO-Section 4.2 Job Processing (贪心)

24 篇文章 0 订阅

描述

一家工厂的流水线正在生产一种产品,这需要两种操作:操作A和操作B。每个操作只有一些机器能够完成。

Ioi96d1.gif

上图显示了按照下述方式工作的流水线的组织形式。A型机器从输入库接受工件,对其施加操作A,得到的中间产品存放在缓冲库。B型机器从缓冲库接受中间产品,对其施加操作B,得到的最终产品存放在输出库。所有的机器平行并且独立地工作,每个库的容量没有限制。每台机器的工作效率可能不同,一台机器完成一次操作需要一定的时间。

给出每台机器完成一次操作的时间,计算完成A操作的时间总和的最小值,和完成B操作的时间总和的最小值。

注:1、机器在一次操作中干掉一个工件; 2、时间总和的意思是最晚时间点

格式

PROGRAM NAME: job

INPUT FORMAT:

(file job.in)

第一行 三个用空格分开的整数:N,工件数量 (1<=N<=1000);M1,A型机器的数量 (1<=M1<=30);M2,B型机器的数量 (1<=M2<=30)。

第二行…等 M1个整数(表示A型机器完成一次操作的时间,1..20),接着是M2个整数(B型机器完成一次操作的时间,1..20)

OUTPUT FORMAT:

(file job.out)

只有一行。输出两个整数:完成所有A操作的时间总和的最小值,和完成所有B操作的时间总和的最小值(A操作必须在B操作之前完成)。

SAMPLE INPUT

5 2 3
1 1 3 1 4

SAMPLE OUTPUT

3 5

完成A操作的时间总和最小值很容易想到

但是完成B操作的时间总和最小值还不是能理解,觉得A操作完成的时间对B操作的时间影响很大

贴一下别人的证明:

问题证明

by true(cai 教的)

现在来证明为什么在第一步最优的前提下能得出第二步最优: 假设在A已经最优的前提下,可以把一个零件拿出放到另一个A的机器上,使得B最后的结果比当前好,那么假设这两台A机器为A1,A2,对应的两台B机器为B1,B2.对应的时间有分别是a1,a2,b1,b2.且a2>=a1,b2>=b1,a2/2<=a1<=a2,b2/2<=b1<=b2. 那么原来A最优时的结果应该是max1{a1+b2,a2+b1},而现在如果把A的一个机器(假设是A2)的零件放到了A1上,那么现在的最优值就为 max2{a1+a2+b1,b2},现在只要证明max1恒<=max2就可以了,分四种情况证明: 一:

假设:
     a2+b1>=a1+b2,
     b2>=a1+a2+b1
     且b2<a2+b1.    
证明:
     由a2+b1>=a1+b2  =>   a2+b1>=b2  (1)
     由b2>=a1+a2+b1  =>   a2+b1<=b2  (2)
     综合(1)(2)可知  a2+b1=b2 与假设矛盾.

二:

假设:
     a2+b1>=a1+b2,
     a1+a2+b1>=b2
     且a1+a2+b1<a2+b1  <<=  显然不成立

三:

假设:
     a1+b2>=a2+b1, (1)
     b2>=a1+a2+b1
     且b2<a1+b2  (4)
证明:
   由b2>=a1+a2+b1  =>  b2-a1>=a2+b1  (2)
  (1)+(2)  =〉 b2>=a2+b1  (3)
   (3)(4)矛盾。

四:

假设:
      a1+b2>=a2+b1,   (1)
      a1+a2+b1>=b2    (2)
    且a1+a2+b1<a1+b2  (3)
证明:
     现在对不等式进行一种等价变换,在不影响(1)(2)不等式符号和a1+b2,a1+a2+b1的差的
     前提下,来试图证明不等式(3)是不可能的
    让a1=a2,则(1)==>>  a2+b2>=a2+b1
                (2)==>>  2a2+b1>=b2
                (3)==>>  2a2+b1<a2+b2
    
   观察(2),(3),应为a2>=0,所以显然是不可能同时成立的,所以问题得证。

即:

在A为最优的前提下一定能够造出一个问题二也是最优的解。

/*
ID: your_id_here
PROG: job
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

int n,am,bm,ans;
int a[205],b[205],atime[1005],btime[1005];

struct aNode {
    int index,time;

    bool operator < (const aNode& x) const{
        return (time+a[index])>(x.time+a[x.index]);
    }
}u;

struct bNode {
    int index,time;

    bool operator < (const bNode& x) const{
        return (time+b[index])>(x.time+b[x.index]);
    }
}v;

priority_queue<aNode> aq;
priority_queue<bNode> bq;

int main() {
    freopen("job.in","r",stdin);
    freopen("job.out","w",stdout);

    scanf("%d%d%d",&n,&am,&bm);
    u.time=0;
    for(int i=0;i<am;++i) {
        scanf("%d",a+i);
        u.index=i;
        aq.push(u);
    }
    for(int i=0;i<n;++i) {//每次取最终时间最小的出来加工
        u=aq.top();
        aq.pop();
        u.time+=a[u.index];
        atime[i]=u.time;
        aq.push(u);
    }
    v.time=0;
    for(int i=0;i<bm;++i) {
        scanf("%d",b+i);
        v.index=i;
        bq.push(v);
    }
    for(int i=0;i<n;++i) {//每次取最终时间最小的出来加工
        v=bq.top();
        bq.pop();
        v.time+=b[v.index];
        btime[i]=v.time;
        bq.push(v);
    }
    sort(atime,atime+n);
    sort(btime,btime+n);
    ans=0;
    for(int i=0;i<n;++i)
        ans=max(ans,atime[i]+btime[n-i-1]);
    printf("%d %d\n",atime[n-1],ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值