独立任务最优调度问题

问题描述:独立任务最优调度,又称双机调度问题:用两台处理机A和B处理n个作业。设第i个作业交给机器A处理时所需要的时间是a[i],若由机器B来处理,则所需要的时间是b[i]。现在要求每个作业只能由一台机器处理,每台机器都不能同时处理两个作业。设计一个动态规划算法,使得这两台机器处理完这n个作业的时间最短(从任何一台机器开工到最后一台机器停工的总的时间)。研究一个实例:n=6,
a = {2, 5, 7, 10, 5, 2}, b = {3, 8, 4, 11, 3, 4}.

分析:当完成k个作业,设机器A花费了x时间,机器B所花费时间的最小值肯定是x的一个函数,设F[k][x]表示机器B所花费时间的最小值。则F[k][x]=Min{
F[k-1][x]+b[k], F[k-1][x-a[k]]
};其中F[k-1][x]+b[k]表示第k个作业由机器B来处理(完成k-1个作业时机器A花费的时间仍是x),F[k-1][x-a[k]]表示第k个作业由机器A处理(完成k-1个作业时机器A花费的时间是x-a[k])。

那么单个点对较大值Max(x,
F[k][x]),表示此时(即机器A花费x时间的情况下)所需要的总时间。而机器A花费的时间x是变化的,即x=0,1,2……x(max),(理论上x的取值是离散的,但为编程方便,设为整数连续的)由此构成了点对较大值序列。要求整体时间最短,取这些点对较大值序列中最小的即是。

理解难点在于B是A的函数表达式,也即动态规划所在。花点时间,看懂表达式,加上思考,理解了这点一切OK,后面的编程实现完全依据这个思想。先用前两个任务的枚举示例来帮助理解。

示例:前两个作业示例足矣。

初始化第一个作业:下标以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,∞}=11,进而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中所有元素之和的最小值。王晓东《算法设计与实验题解》中提供的方法时间复杂度是O(m*m*n*n*n),其中m为a、b所有元素的最大值。
      比较:Sum必然远远小于n*m;所以n*Sum<n*n*m,相比之下差了O(n*m)都不止,看来这个思想还是蛮优秀的。。。。

程序如下,数据通过“input.txt”输入:

#include<iostream> 
#include<fstream>
#include<iomanip>  
using
namespace std;  
const int SIZE=50;  
const int
MAXINT=999;  
int
main(){  
      
while(1){  
int
N,a[SIZE],b[SIZE],SumA[SIZE],SumB[SIZE];  
int
tempSumA,tempSumB,MinSum;  
int
i=0,j,k;  
tempSumA=tempSumB=0;
int data;
int
oriData[SIZE]; 
//记录A,B完成当前任务所需时间  
//Read
input.txt
 ifstream ifile;
   
ifile.open("input.txt");  
 if(ifile.eof()) 
   
{
        cerr<<"Fail to open the
file input.txt"<<endl;
       
return 1;
   
}
while(ifile>>data)
   
{
  oriData[i++]=data;    //Recording
data
    }

N=(int)oriData[0];    //the number of
task
// i=0;
 for
(i=1;i<=N;i++)
 {
  a[i]=oriData[i];
  tempSumA+=a[i];  
  SumA[i]=tempSumA;
 }
 for
(i=1,j=N+1;j<=2*N;j++,i++)
 {
  b[i]=oriData[j];
  tempSumB+=b[i];  
  SumB[i]=tempSumB;
 }

//Show data of input.txt and data will
process.
 cout<<"Input.txt
Data:"<<endl;
 cout<<oriData[0]<<endl;
 for
(i=1;i<=2*N; )
 {
  cout<<oriData[i]<<"
";
  i++;
  cout<<oriData[i]<<endl;
  i++;  
 }
/* cout<<"Data
will process:"<<endl;
 for
(i=0;i<cnt;i++)
 {
  cout<<proData[i]<<"
";
 }*/
 cout<<endl;
   
ifile.close();
/*cin>>N;  
if(N<=0)break;  
int
tempSumA,tempSumB,MinSum;  
int
i,j,k;  
tempSumA=tempSumB=0;  
for(i=1;i<=N;i++){  
cin>>a[i];  
tempSumA+=a[i];  
SumA[i]=tempSumA;  
}  
for(i=1;i<=N;i++){  
cin>>b[i];  
tempSumB+=b[i];  
SumB[i]=tempSumB;  

*/
MinSum=(tempSumB>tempSumA)?tempSumA:tempSumB;  
//时间上限AB总和的最小值  
///动态二维数组   
int
*MaxTime=new int [MinSum+1];  
int **F=new
int*[N+1];  
for(i=0;i<N+1;i++)  
F[i]=new int
[MinSum+1];  
SumB[0]=0;  
for(i=0;i<=N;i++){  
F[i][0]=SumB[i];//SumB[0]没赋值,调试时会输出地址   
for(j=1;j<=MinSum;j++)  
F[i][j]=0;  
}  
/*for(i=0;i<=N;i++){ 
for(j=0;j<=MinSum;j++) 
cout<<setw(2)<<F[i][j]<<"
"; 
cout<<endl; 

cout<<endl;*/  
int
temp;  
for(k=1;k<=N;k++){  
  
temp=(SumA[k]>SumB[k])?SumB[k]:SumA[k];  
  
for(i=1;i<=temp;i++){
//A最多用AB前k任务的最小值,如果B最少就全用B做。  
     
if(i>=a[k])//等于号不能少   
   
F[k][i]=(F[k-1][i]+b[k]<F[k-1][i-a[k]])?F[k-1][i]+b[k]:F[k-1][i-a[k]];  
     
else
F[k][i]=F[k-1][i]+b[k];  
                       
}   
                 
}  
                    
/*for(i=0;i<=N;i++){ 
for(j=0;j<=MinSum;j++) 
cout<<setw(2)<<F[i][j]<<"
"; 
cout<<endl; 
                 

cout<<endl;     
*/  
        
temp=MAXINT;  
for(i=0;i<=MinSum;i++){  
 MaxTime[i]=(i>F[N][i])?i:F[N][i];  
if(temp>MaxTime[i])  
temp=MaxTime[i];  
                      
}  
//cout<<temp<<endl;

//out.txt
ofstream ofile;  //write
file
 ofile.open("output.txt");
/* int
result=0;
 for(int
i=0;i<c;i++)
 {
  result+=abs(Data[i]-m);
 }*/
 ofile<<temp<<endl;
ofile.close();
cout<<"最优时间为:"<<temp<<endl;
while(1);
///////////////////////////////////  
/*for(i=0;i<N+1;i++)  
delete
[] F[i];  
delete [] F;  
delete []
MaxTime;  
F=NULL;  
*/
}  
////////////////////////////////  
//system("pause");  
//return
0;      
   
}

时间: 2024-12-18 11:32:28

独立任务最优调度问题的相关文章

【动态规划】流水作业调度问题与Johnson法则

1.问题描述:     n个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工.每个作业加工的顺序都是先在M1上加工,然后在M2上加工.M1和M2加工作业i所需的时间分别为ai和bi.流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少.     2.问题分析 直观上,一个最优调度应使机器M1没有空闲时间,且机器M2的空闲时间最少.在一般情况下,机器M2上会有机器空闲和作业积压2种情况.设全部作

独立IP与共享IP的区别

做网站选择独立IP还是共享IP,相信很多站长都在此纠结过,自己不使用服务器的时候从来没有关心过独立IP和共享IP的究竟有什么具体的差别.但当自己真正用到的时候,才发现:同样都是 IP,差别不是一般的大,独立IP的强悍,不用的人是没有办法体会的.奉劝亲爱的站友们, 选择IP的时候一定要慎重的考虑好了. 对于大部分网站来说,使用的都是共享IP,我们可以把共享IP理解成,一个房子租给了多个人居住,肯定彼此间有影响和打扰,但是胜在价格便宜.而独立IP的好处就是一个人住,清净.安全.上面的比喻,也就好比是

流水作业调度问题与Johnson法则

1.问题描述:     n个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工.每个作业加工的顺序都是先在M1上加工,然后在M2上加工.M1和M2加工作业i所需的时间分别为ai和bi.流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少.     2.问题分析 直观上,一个最优调度应使机器M1没有空闲时间,且机器M2的空闲时间最少.在一般情况下,机器M2上会有机器空闲和作业积压2种情况.设全部作

独立IP与共享IP有什么区别呢?

做网站选择独立IP还是共享IP?相信很多站长都在此纠结过,自己不使用服务器的时候从来没有关心过独立IP和共享IP的究竟有什么具体的差别.但当自己真正用到的时候,才发现:同样都是IP,差别不是一般的大,独立IP的强悍,不用的人是没有办法体会的 做网站选择独立IP还是共享IP?相信很多站长都在此纠结过,自己不使用服务器的时候从来没有关心过独立IP和共享IP的究竟有什么具体的差别.但当自己真正用到的时候,才发现:同样都是IP,差别不是一般的大,独立IP的强悍,不用的人是没有办法体会的.奉劝亲爱的站友们

流水作业调度问题

<span style="font-weight: bold; font-family: Arial; line-height: 26px; font-size: 12px; background-color: rgb(255, 255, 255); margin: 0px; padding: 0px;"><span style="font-size: 24px;"><span style="margin:0px; paddi

算法期末备考-第5练-动态规划

算法期末备考-第5练 [主要内容] 动态规划 背包类型的dp:01背包 线性dp:最长公共子序列,编辑距离 经典例题: 独立任务最优调度,最大子段和 01背包 [题目链接] https://www.acwing.com/problem/content/2/ [题目描述] 有 N 件物品和一个容量是 V 的背包.每件物品只能使用一次. 第 i 件物品的体积是 vi,价值是 wi. 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大. 输出最大价值. [数据范围] 0<N,V≤

深信服模式(先做减法,必须拜访客户三次、研究需求方向,把产品的问题控制住,快速反应,在未来十年,绝大部分业务都会搬到Internet上来,实现All on Internet)good

深圳市盛凯信息科技有限公司与深信服合作多年,可以说是看着深信服“飞速”长大的.盛凯的总经理邓渊在采访中笑言:“他们(深信服)发展得太快,而我们发展得太慢.” 深信服的产品线已从最初只有VPN一条,到目前包括上网行为管理.广域网优化.应用交付.下一代防火墙.应用性能管理和虚拟化等多条产品线.根据IDC的报告,在中国的网络安全市场上,深信服已经进入前三甲.而这只是深信服其中内容安全管理和VPN两条产品线的成绩. 对复杂市场的精准定位:对需求趋势的精准解读:对客户及合作伙伴的深度沟通:对创新意识的极度

MySQL与OLAP:分析型SQL查询最佳实践探索

搞点多维分析,糙快猛的解决方案就是使用ROLAP(关系型OLAP)了.数据经维度建模后存储在MySQL,ROLAP引擎(比如开源的Mondrian)负责将OLAP请求转化为SQL语句提交给数据库.OLAP计算分析功能导致MySQL需要进行较多复杂SQL查询,性能调优必不可少,本文总结了一些实用原则. OLAP特点 OLAP的典型应用包括复杂动态报表,需要支持钻取(上卷和下钻).切片.切块和旋转操作.下表总结了OLAP和OLTP系统的主要区别.OLAP的特点决定了SQL的查询场景和优化方案,下文将

贪心算法-----单线程:活动安排问题 多线程:多机调度问题

一.贪心算法的特点 顾名思义,贪心算法总是做出在当前看来是最好的选择.虽然贪心算法并不从整体最优上加以考虑,它所做出的选择只是在某种意义上的局部最优选择. 贪心算法的优点是更简单,更直接且解题效率更高,即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好的近似解. 二.贪心算法的理解 由于涉及到在做出在当前看来最好的选择,所以会经常采用排序算法,推荐使用快速排序算法,复杂度是O(nlgn),且在同等复杂度算法中效率是最高的, 本文涉及的排序都采用冒泡排序,只是注明需要排序而已. 贪心算法