概述
算法分析与设计
1. 独立任务最优调度问题
问题描述:用两台处理机A和B处理n个作业。设第i个作业交给机器A处理时间需要a[i],若由机器B来处理,则需要时间b[i]。由于各作业的特点和机器的性能关系,很可能对于某些i,有a[i]≥b[i],而对于某些j,j≠i,有aj<bj。既不能将一个作业分开由两台机器处理,也没有一台机器能同时处理两个作业。设计一个动态规划算法,使得这两台机器处理完这n个作业的时间最短(从任何一台机器开工到最后一台机器停工的总时间)。
输入格式:
第1行是1个正整数n,表示要处理n个作业。在接下来的两行中,每行有n个正整数,分别表示处理器A和B处理第i个作业需要的处理时间。
输出格式: 将计算出的最短处理时间输出。
样例输入:
6
3 5 7 10 5 2
3 8 4 11 3 4
样例输出:
15
分析:当完成k个作业时,设机器A花费的时间为x,则机器B花费的时间的最小值为x的一个函数,设F[k,x]表示在完成k个作业时机器A花费时间x的条件下,机器B所花费时间的最小值。递推式:F[k,x]= min {F[k-1,x]+ b[k] , F[ k-1, x-a[k] ]} 。注意:F是机器B所花最小时间,是关于机器A在分配给它x的条件下的一个函数! F [k-1 , x] + b[k] 表示第k个作业由机器B来处理,,F[ k-1, x-a[k]] 表示第k个作业由机器A处理 ,知道为什么是这样子的吗?我也不知道哈哈哈哈,但是你可以通过理解这个递推式来说明这个递推式是正确可行的,要我自己想我也想不出来这个式子555。
也就是说如果把作业k给机器B完成,则完成作业k时,机器A花费时间x的前提下B所花最小时间就等于(完成上一个作业k-1,机器B在机器A花费x的前提下,B所花最小时间)加上(作业K机器B所完成的时间).如果第k个作业要给A完成的话,则完成作业k时,机器A花费x分钟的条件下,则完成作业k-1时,机器A所需时间为x-a[k],所以如果作业k让机器A花费x时间的前提下,机器B所花时间最小值就等于完成作业k-1时,机器A花费x-a[k]时间,B所需最少时间 . (是不是很绕!!!我也快绕晕了,|@_@|,有没有易于理解的想法也可以告诉我,我不知道自己是不是理解复杂了555)
PS:递推式一定要理解!!!
之后我们来计算max{ x , f [k,x] },得到此时所需要的总时间。为了编程方便,我们将x设为连续值(理论上x是离散值),x是连续变化的,所以我们计算出的max值可以构成一个序列,再求出这个序列中的最小值即可达到题目要求.
示例:前两个作业。
初始化第一个作业:下标以0开始。
首先,机器A所花费时间的所有可能值范围:0 <= x <= a[0].
设x<0时,设F[0][x]= ∞,则max(x, ∞)= ∞;记法意义见下。
x=0时,F[0][0]=3,则Max(0,3)=3;
机器A花费0时间,机器B花费3时间,而此时两个机器所需时间为3;
x=1时,F[0][1]=3,Max(1,3)=3;
x=2时,F[0][2]=0,则Max(2,0)=2;
那么上面的点对序列中,可以看出当x=2时,完成第一个作业两台机器花费最少的时间为2,此时机器A花费2时间,机器B花费0时间。
来看第二个作业:
首先,x的取值范围是:0 <= x <= (a[0] + a[1]).
当x<0时,记F[1][x] = ∞;这个记法编程使用,因为数组下标不能小于0。在这里的实际含义是:x是代表完成前两个作业机器A的时间,a[1]是机器A完成第2个作业的时间,若x<a[1],则势必第2个作业由机器B来处理,即在Min()中取前者。
x=0,则F[1][0]= Min{ F[0][0]+b[2], F[0][0-a[1]] }= Min{3+8,∞}=1,Max(0,11)=11;
x=1,则F[1][1]= Min{ F[0][1]+b[2], F[0][1-a[1]] }= Min{3+8,∞}=11,Max(11)=11;
x=2,则F[1][2]= Min{ F[0][2]+b[2], F[0][2-a[1]] }= Min{0+8,∞}=8,Max(2,8)=8;
x=3,则F[1][3]= Min{ F[0][3]+b[2], F[0][3-a[1]] }= Min{0+8,∞}=8,Max(3,8)=8;
x=4,则F[1][4]= Min{ F[0][4]+b[2], F[0][4-a[1]] }= Min{0+8,∞}=8,Max(4,8)=8;
x=5,则F[1][5]= Min{ F[0][5]+b[2], F[0][5-a[1]] }= Min{0+8,3}=3,Max(5,3)=5;
x=6,则F[1][6]= Min{ F[0][6]+b[2], F[0][6-a[1]] }= Min{0+8,3}=3,Max(6,3)=6;
x=7,则F[1][7]= Min{ F[0][7]+b[2], F[0][7-a[1]] }= Min{0+8,0}=0,Max(7,0)=7;
那么上面的点对序列中,可以看出当x=5时,完成两个作业两台机器花费最少的时间为5,此时机器A花费5时间,机器B花费3时间。
算法时间复杂度:按照上述思想,编程实现,结果如上图,算法时间复杂度为O(n*Sum),其中Sum为a中所有元素之和与b中所有元素之和的最小值。
C语言代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#define MAXN 1005
int a[MAXN];//机器A处理各作业的时间
int b[MAXN];//机器B处理各作业的时间
int F[MAXN][MAXN];//
int time[MAXN];//处理作业k所需要的最短时间
int n;
void read() {
printf("请输入作业数量:");
scanf("%d",&n);
printf("请输入机器A处理每个作业的时间:");
for(int i = 1; i <= n; i++) {
scanf("%d",&a[i]);
}
printf("请输入机器B处理每个作业的时间:");
for(int i = 1; i <= n; i++) {
scanf("%d",&b[i]);
}
}
int min(int x, int y) {
return x < y ? x : y;
}
int max(int x, int y) {
return x > y ? x : y;
}
int schedule() {
int sumA = a[1];
//k = 1的情况
for(int x = 0; x < a[1]; x++) {
F[1][x] = b[1];
}
F[1][a[1]] = min(b[1],a[1]);
//初始化
for(int i = 2; i <= n; i++) {
for(int j = 0; j <= n; j++) {
F[i][j] = INT_MAX;
}
}
//k >= 2的情况
for(int k = 2; k <= n; k++) {
sumA += a[k];
time[k] = INT_MAX;
for(int x = 0; x <= sumA; x++) {
if(x < a[k]) {
//即如果分配给机器A的时间少于A完成该作业所需时间,就相当于该作业让Bu去做了
F[k][x] = F[k-1][x] + b[k];
} else {
//如果分配给机器A的时间足够,则再讨论在分配给A x时间下,B所需最小时间
F[k][x] = min(F[k-1][x] + b[k], F[k-1][x-a[k]]);
}
//判断完成作业k时,到底是机器B所需最小时间小,还是A所需时间小
time[k] = min(time[k],max(x,F[k][x]));
}
}
return time[n];
}
int main(void) {
read();
printf("总的最少处理时间为:%dn",schedule());
return 0;
}
运行结果如下:
最后
以上就是美好高山为你收集整理的动态规划-双机调度1. 独立任务最优调度问题的全部内容,希望文章能够帮你解决动态规划-双机调度1. 独立任务最优调度问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复