雙機流水作業調度問題(Johnson算法)


問題定義:

雙機流水作業調度:總共有n個作業,作業\(i\)分為兩個內容,需要按順序先后在機器A和機器B上完成,分別需要時間\(a_i,b_i\)來完成,一台機器只能同時進行一項作業,問完成所有作業所需的最小時間。

多機流水作業調度:一個作業需要在大於兩台機器上先后完成,是NP-hard問題。

解法:

問題就是求最佳作業序列。設前i項作業所需的時間為\(C_i\),可以得出以下式子

\[c_{i}=\left\{\begin{array}{ll}a_{1}+b_{1} & , i=1 \\\max \left\{c_{i-1}, \sum_{j=1}^{i} a_{j}\right\}+b_{i} & , 2 \leq i \leq n\end{array}\right. \]

可以證明,對於相鄰兩項i和j,如果\(min(a_i,b_j)<min(a_j,b_i)\)則i項放前面更優。

\(a_i\)\(b_i\)的關系分為<,=,>三類,可以得到如下排列順序:

1.當 \(a_{i}<b_{i}, a_{j}<b_{j}\) 時, \(a_{i} \leq a_{j},\) 應該按a升序排序
2.當 \(a_{i}=b_{i}, a_{j}=b_{j}\) 時,隨意排列。
3.當 \(a_{i}>b_{i}, a_{j}>b_{j}\) 時, \(b_{i} \geq b_{j},\) 應該按b降序排序。

同樣可以證明,\(a_i<b_i\)的項應該排在最前,然后是\(a_i=b_i\)的項,最后是\(a_i>b_i\)的項。

代碼:

//P1248,給定n,ai,bi,求最小用時和對應序列
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long ll;
struct node{
    int a,b,d,id;
    bool operator<(const node &v)const {
        if(d!=v.d)return d<v.d;
        else if(d==-1){
            return a<v.a;
        }
        else{
            return b>v.b;
        }
    }
}p[maxn];
int main () {
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&p[i].a);
    for(int i=1;i<=n;i++){
        scanf("%d",&p[i].b);
        p[i].id=i;
        int cha=p[i].a-p[i].b;
        if(cha==0)p[i].d=0;
        else p[i].d=cha<0?-1:1;
    }
    sort(p+1,p+1+n);
    ll ans=0,dt=0;
    for(int i=1;i<=n;i++){
        ans+=p[i].a;
        dt=max(0ll,dt-p[i].a);
        dt+=p[i].b;
    }
    ans+=dt;
    printf("%lld\n",ans);
    for(int i=1;i<=n;i++){
        if(i>1)printf(" ");
        printf("%d",p[i].id);
    }
    puts("");
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM