AOJ-AHU-OJ-145 流水线作业调度问题
来源:互联网 发布:淘宝ebay代购流程 编辑:程序博客网 时间:2024/04/30 11:22
流水线作业调度问题
Time Limit: 1000 ms Case Time Limit: 1000 ms Memory Limit: 64 MB
Description
N个作业{1,2,………,n}要在由两台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工。M1和M2加工作业i所需的时间分别为ai和bi,1≤i≤n。
流水作业高度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。
流水作业高度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。
Input
输入包括若干测试用例,每个用例输入格式为:
第1行 一个整数代表任务数n,当为0时表示结束,或者输入到文件结束(EOF)
第2行至第n+1行每行2个整数,代表任务在M1,M2上所需要的时间
第1行 一个整数代表任务数n,当为0时表示结束,或者输入到文件结束(EOF)
第2行至第n+1行每行2个整数,代表任务在M1,M2上所需要的时间
Output
输出一个整数,代表执行n个任务的最短时间
Sample Input
OriginalTransformed11 20
Sample Output
OriginalTransformed3
——————————————————————分割线——————————————————————
思路:这一题的难度还是相当不小的。首先是一个两道工序的流水线排序问题(“同顺序”排序问题)。用Johnson算法来解决两道工序的流水线排序相对比较简单易懂,而且可以得到最优解。Johnson算法的大致内容如下:
(1)从加工时间矩阵中找出最短的加工时间。
(2)若最短的加工时间出现在M1上,则对应的工件尽可能往前排;若最短加工时间出现在M2上,则对应工件尽可能往后排。然后,从加工时间矩阵中划去已排序工件的加工时间。若最短加工时间有多个,则任挑一个。
(3)若所有工件都已排序,停止。否则,转步骤(1)。
加工时间矩阵即为所有工件分别在两道工序上加工所需时间。M1为工序1,M2为工序2(进入工序2之前,工序1必须完工)。Johnson算法之所以能求出最优解,是因为:1.所有工件没开始加工时,只能加工工序1,工序2不得不空着。2.我们只能利用工序2的加工过程尽量省去工序1的时间。3.最后一个工件的工序2加工时间无法省去。所以“第i个”最小值如果为工序1,尽早加工,“第i个”最小值如果为工序2,最晚加工。(i = 1……n)
完成排序之后,计算工时。工时的计算我是模拟出来的。我姑且称之为双线计时。
代码如下:
#include <stdio.h>int wk[10000], work[10000][3];int mini[3], n;//这里的最小值mini我开成了数组,分为三个部分。mini[0]保存的是最小值,mini[1]保存的是最小值类型(当前最小是工序1 or 工序2)mini[2]是任务号void Findmi(){ int i; for(i = 0; i < n; i++){ if(!work[i][2]){//如果该工件还未进行排序,分别看它的工序1工序2耗时,最后找到所有耗时中最小的 if(work[i][0] < mini[0]){ mini[0] = work[i][0]; mini[1] = 0; mini[2] = i; } if(work[i][1] < mini[0]){ mini[0] = work[i][1]; mini[1] = 1; mini[2] = i; } } }//经过了一轮for循环之后,mini[0]保存的就是第一次寻找最小值的结果,mini[1]记录的是该值为工序1还是工序2,mini[2]记录的是工件的任务号 work[mini[2]][2] = 1;//做已排序记录}int Time(){//这个工时计算,相当得……TAT还是看变量吧! int i = 0, j = 0, k = 0, v = 0;//i表示用时统计,j表示循环条件,使用k和v用作双线计时标记,即计时器1和计时器2,我们可以画一张工时计算图理解它们 for(;j < n; j++){ i = k;//进入循环体,更新i为当前k所在位置,k代表上次工序1使用完毕后计时器1显示的时间 while(work[wk[j]][0]--)//该工件工序1未完成 i++;//在工序1上进行加工 k = i;//工序1加工完成,k标记此时i所在位置,它意味着必须要等到Machine 1空闲才能运作 if(v < k) v = k;//注意,此处补丁很重要,在i更新为v所在位置之前,一定要确认v在k的后面 i = v;//更新i为当前v所在位置,v代表上次工序2使用完毕后计时器2显示的时间 while(work[wk[j]][1]--)//该工件工序2未完成 i++;//在工序2上进行加工 v = i;//工序2加工完成,v标记此时i所在位置,它意味着必须要等到Machine 2空闲才能运作 } return i;}int main(){int i, k, g;int m;while(scanf("%d", &n) != EOF&&n){ m = n; //下面会在计算中使用到任务数,因此保存下来,用任务号给工件们做编号 for(i = 0; i < n; i++){ scanf("%d%d", work[i]+0, work[i]+1);//work[][0]保存工序1所花时间,work[][1]保存工序2所花时间 work[i][2] = 0;//work[][2]用来记录该工件是否已经排序,相当于将每个工件的工序1耗时、工序2耗时连锁起来 } for(k = 0,g = n-1;m > 0; m--){//排序直到所有工件参与后截止 mini[0] = 100000000; Findmi();//每次使用Findmi()函数之后,找到一个未参与排序的工件的最小值 if(!mini[1])//如果它是工序1的,就排到最前面,否则最后面 {wk[k] = mini[2];k++;}//wk数组,-_-b汗颜,这么多奇怪的数组哈!保存了排序后的工件编号 else {wk[g] = mini[2];g--;}//一个k++,一个g--,判定条件用m,好一个两边夹! } printf("%d\n", Time());//打印最省时方案的耗时}return 0;}
0 0
- AOJ-AHU-OJ-145 流水线作业调度问题
- AOJ-AHU-OJ-453 棋盘问题
- 流水线作业调度问题
- AOJ-AHU-OJ-453 棋盘问题(位压缩)
- AOJ-AHU-OJ-2 Homework
- AOJ-AHU-OJ-9 University
- AOJ-AHU-OJ-11 Rails
- AOJ-AHU-OJ-542 Window
- AOJ-AHU-OJ-489 夺宝奇兵
- AOJ-AHU-OJ-676 投票
- AOJ-AHU-OJ-531 IPv4
- AOJ-AHU-OJ-31 Counting Sheep
- AOJ-AHU-OJ-6 Hero in Maze
- AOJ-AHU-OJ-3 Redraiment的遭遇
- AOJ-AHU-OJ-5 渊子赛马
- AOJ-AHU-OJ-7 Redraiment猜想
- AOJ-AHU-OJ-8 童年生活二三事
- AOJ-AHU-OJ-394 Fibonacci numbers
- CSS table 表格边框粗细控制详细代码
- poj2488
- 未处理的异常: 0xC0000005: 读取位置 0x00000000 时发生访问冲突
- myeclipse设置代码模板Code Templates
- VC++获得当前系统时间的几种方案
- AOJ-AHU-OJ-145 流水线作业调度问题
- 一.1
- sqoop1.4.4命令
- hashmap中equals() 和hashcode()
- 将接近传感器和环境光传感器封装在一起的优点
- Hadoop 的 TotalOrderPartitioner<转>
- MFC中CTreeCtrl右击选中节点并弹出右击菜单
- Android命令行工具logcat详细用法
- 【项目1 - 用枚举表示对称方式】