zoukankan      html  css  js  c++  java
  • #蓝书整理 流水作业调度问题

    流水作业调度问题

    题目描述

    某工厂收到了 n个产品的订单,这 n个产品分别在 A、B 两个车间加工,并且必须先在 A 车间加工后才可以到 B 车间加工。

    某个产品 i 在 A、B 两车间加工的时间分别为 (A_i,B_i)。怎样安排这 n 个产品的加工顺序,才能使总的加工时间最短。

    这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A、B 两车间加工完毕的时间。

    Johnson算法

    算法描述

    直观思想:让1号不停工作,让2号等待的最少。

    (N_1)为 a < b 的作业集合,设(N_2)为 a > b 的作业集合,将 (N_1) 的作业集合按照(a_i)升序排列,将(N_2) 的按照(b_i)降序排列。(N_1)放在(N_2)后面构成最优顺序。

    时间复杂度:(O(n log n))

    首先有:第一个部件在A加工时B在等待,最后一个部件在B加工时A在等待。猜想使总的空闲时间最短就是答案。那么A应该先加工在A上时间最短的,同理,B应该最后加工在B上时间最短的。于是就有了这样的贪心策略:

    (M_i = min { a_i , b_i })

    将M按照从小到大的顺序排序,从第一个开始处理,若 (M_i = a_i) 就放到前面,如果 (M_i = b_i) 就放到后面。

    证明

    (S = { J_1,J_2····,J_n})为待加工部件的作业顺序。若A开始加工S中的部件时,B机器还在加工其他部件,t时刻后B机器可加工A加工过的部件。则这种情况下最短时间为

    [T(S,t) = min(a_i + T(S - J_i , b_i + max(t-a_i,0))) (J_i属于S) ]

    假设最佳方案中,先加工作业(J_i),再加工(J_j),则有

    [T(S,t) = a_i +T(S-J_i , b_i+max(t-a_i,0)) \ = a_i + a_j +T(S-J_i-J_j , b_j +max(b_i + max(t-a_i,0)-a_j,0)) \ = a_i + a_j + T(S - J_i-J_j , T_{ij}) \ T_{ij} = b_j +max(b_i + max(t-a_i,0)-a_j,0)) \ ]

    把max里面的((b_i-a_j-a_i))提到外面来

    [= b_i + b_j - a_j-a_i +max(t , a_i , a_i +a_j - b_i) ]

    如果调换 $ J_i , j_j $的顺序,就有

    [T'(S,t) = a_i + a_j + T(S - J_i-J_j,T_{ij}) ]

    其中,

    [T_{ij} = b_i + b_j - a_j-a_i +max(t , a_j , a_i +a_j - b_j) ]

    [min(b_j,a_i)leq min(b_i,a_j) ]

    点这里继续!!!

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int ans[1005],n,k,i,j,t,a[1005];
    int b[1005],m[1005],s[1005];
    void read(){
    	cin >> n;
    	for(i = 1;i <= n;i++) cin >> a[i];
    	for(i = 1;i <= n;i++) cin >> b[i];
    	for(i = 1;i <= n;i++){ m[i]=min(a[i],b[i]);s[i]=i;}
    }
    void solve(){
    	for(i = 1;i <= n-1;i++)
    		for(j = i+1;j <= n;j++){
    			if(m[i] > m[j]) {swap(m[i],m[j]);swap(s[i],s[j]);}
    		}
    	k = 0;t = n + 1;
    	for(i = 1;i <= n;i++){
    		if(m[i] == a[s[i]]){k++;ans[k] = s[i];}
    		else {t--;ans[t] = s[i];}
    	}
    	k = 0;t = 0;
    	for(i = 1;i <= n;i++){
    		k += a[ans[i]];
    		if(t < k) t = k;
    		t += b[ans[i]];
    	}
    	cout << t << endl;
    	for(i = 1;i <= n;i++) cout << ans[i] << ' ';
    	cout << endl;
    }
    int main(){
    	read();
    	solve();
    	return 0;
    }//lcez_cyc
    
  • 相关阅读:
    常用的python模块
    程序人生--世界观
    JQuery与CSS之图片上放置button
    所谓的成就感,想想我们測过的那些功能
    王立平-bmp.compress()
    Android多媒体学习六:利用Service实现背景音乐的播放
    NHibernate3剖析:Mapping篇之集合映射基础(3):List映射
    freeradius 启动报错Refusing to start with libssl version OpenSSL 1.0.1
    超级简单JS网页倒计时代码
    一起talk C栗子吧(第一百一十二回:C语言实例--线程同步概述)
  • 原文地址:https://www.cnblogs.com/Cao-Yucong/p/12177760.html
Copyright © 2011-2022 走看看