洛谷P2751 USACO4.2 Job Processing 工序安排 - 贪心

(碎碎念)-。-一开始想了个特别复杂的做法,后来发现写不出来233,看了官方题解被虐的不行。。。

先考虑A工序
考虑到产品是一个个完成的,而所用机器之间平行工作,题问的是时间轴上的最晚点
把机器在时间轴上平行排开,为每个机器分配一些工件,最后最晚完成最后一个机器的时间轴上的点就是最小“时间总和”
那么如何分配工件呢,发现机器的效率是已知的,结合机器曾经工作时间,就可以算出用这个机器完成第i个工件的时间点,找一个最小的,更新机器的曾经工作时间。同时记录下第i个工件完成的最早时间tim1[i]

(时间点,就是目前的最晚时间,最后一个处理的工件一定是最晚处理完的。如果说不是最晚处理完的,上一个工件比他早处理,处理完还比他晚,那我在处理上一个工件时,由于我是贪心地安排工序,我不可能说有能更早处理完的方案,我选择了更晚处理的方案,留更好的机器给下一个工件)

对于B工序,仍然采用上述方法求出tim数组,记作tim2[i],因为A工序必须先于B工序,那么想要对第i个工件加工必须要在tim1[i]之后

先不管A的话,tim2数组表示的是,在B工序中,第i快完成的产品所花的时间,那么考虑A,假设某个工件在A中是第x个完成的,在B中是第y个完成的,那么总时间就是tm1[x] + tm2[y],想要减少总时间,因为不能改变A,只能改变从“缓冲区”给B加工的工件次序,比如说A,1s,3s时分别出了两个产品x1,x2,改变x1,x2在B中处理的次序。

显然,tm1小的工件,他的tm2应该尽量大,才能使最后时间更平均(总时间是tm1 + tm2)

所以我们把tm1最小的安排成tm2最大的,第二小的安排成第二大的,最后答案是max(tm1[i] + tm2[n-i+1])

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 1000 + 10;
int n,ma[MAXN],mb[MAXN],maa,mbb,at[MAXN],bt[MAXN],ans1,ans2,tm1[MAXN],tm2[MAXN];
int main() {
    cin >> n >> maa >> mbb;
    for(int i=1; i<=maa; i++) {
        cin >> ma[i];
    }
    for(int i=1; i<=mbb; i++) {
        cin >> mb[i];
    }

    for(int i=1; i<=n; i++) {
        int minj=1<<30, mint=1<<30;
        for(int j=1; j<=maa; j++) {
            if(at[j] + ma[j] < mint) {
                minj = j, mint = at[j] + ma[j];
            }
        }
        at[minj] = mint;
        tm1[i] = mint;
        if(i == n) ans1 = mint;
    }
    cout << ans1 << " ";
    for(int i=1; i<=n; i++) {
        int minj=1<<30, mint=1<<30;
        for(int j=1; j<=mbb; j++) {
            if(bt[j] + mb[j] < mint) {
                minj = j, mint = bt[j] + mb[j];
            }
        }
        bt[minj] = mint;
        tm2[i] = mint;
    }
    for(int i=1; i<=n; i++) {
        ans2 = max(ans2, tm1[i] + tm2[n-i+1]);
    }
    cout << ans2;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fantasy_world/article/details/81158402
今日推荐