动态规划——独立任务最优调度问题

3-1:独立任务最优调度问题
一、需求分析
问题描述:用2台处理机A和B处理n个作业。设第i个作业交给机器A处理时需要时间ai,若由机器B来处理,则需要时间bi。由于各作业的特点和机器的性能关系,很可能对于某些i,有ai>bi,而对于某些j,j≠i,有aj>bj。既不能将一个作业分开由2台机器处理,也没有一台机器能同时处理2个作业。设计一个动态规划算法,使得这2台机器处理完这n个作业的时间最短(从任何一台机器开工到最后一台机器停工的总时间)。研究一个实例:
(a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2);(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)。
对于给定的2台处理机A和B处理n个作业,找出一个最优调度方案,使2台机器处理完这n个作业的时间最短。

1.问题分析
本题通过给出的n值,给出A,B机器完成每一个作业所需要的时间
输出要求:计算并输出两台机器完成n项任务所需要的最短时间。
2.输入数据
由文件 input.txt提供输入数据。文件的第1行是任务总数n,接下来第一行输入数组a[i]代表A处理第i项任务的时间,第二行输入数组b[i]代表B处理第i项任务所需要的时间。
3.输出数据
计算结果输出到输出文件output.txt中,文件中的数是两台机器完成n项任务所需要的最短时间。
4.测试样例设计
输入文件设计 输出文件设计
Input.txt Output.txt
6 15
2 5 7 10 5 2
3 8 4 11 3 4
二、算法设计
1、算法的基本思想
我们定义一个二维数组F[i][j]代表处理前i项任务,机器A需要j时间时,机器B所需要的最短时间。
接下来我们来考虑这个二维数组的递推式:
F[i][j]中的第i项任务,我们既可以交给A来完成,也可以交给B来完成,选择谁是取决于谁需要的时间少,但是如果j<a[i]的话,这个第i项任务就只能交给B来完成了。
所以我们的递推式是这样的:如果j<a[i],F[i][j]=F[i-1][j]+b[i],否则,F[i][j]=min(F[i-1][j-a[i]],F[i-1][j]+b[i]),
然而,最后我们还需要进行一个判断,因为F[i][j]代表的是完成前i项任务,机器A需要j时间,机器B所需要的最少时间,那么完成前i项任务所需要的最终时间是多少呢?就是两台机器所需时间的最大值,因为两台机器是可以同时进行工作的,所以最后输出F[n][i]与i的最小值,i从0到sum(代表所有a[i]相加的总和)。
3、算法的具体步骤
(1)递推型动态规划函数:如果j<a[i],F[i][j]=F[i-1][j]+b[i],否则,F[i][j]=min(F[i-1][j-a[i]],F[i-1][j]+b[i]),
代码如下:
int sum=0;
for(int i=1;i<=n;i++)
{
sum+=a[i];//完成前i项任务,机器A所需时间的范围
for(int j=0;j<=sum;j++)
{
if(j<a[i]) F[i][j]=F[i-1][j]+b[i];//如果j<a[i],只能交给B完成
else
{
F[i][j]=min(F[i-1][j]+b[i],F[i-1][j-a[i]]); //否则是谁的时间少交给谁完成
}
}
}}
(2)判断
int temp;
int minn=F[n][1];
for(int i=0;i<=sum;i++)
{
temp=max(F[n][i],i);//用的时间是A,B花费时间的最大值
if(temp<minn) minn=temp;
}
return minn;
(2)主函数:分为从文本文件输入输出、调用solve函数。使用fstream头文件中的iftream和ofstream来完成输入输出。开辟一个二维数组来存放F,再用iuput文件中的数据赋给数组初值,最后输出到output文件即可。代码如下:
int main()
{
ifstream infile(“input-3-1.txt”);
ofstream outfile(“output-3-1.txt”);
int n;
infile>>n;
int a[n+1],b[n+1];
for(int i=1;i<=n;i++) infile>>a[i];
for(int i=1;i<=n;i++) infile>>b[i];
int F[n+1][10000];
memset(F,0,sizeof(F));
int *P[n+1];
for(int i=0;i<=n;i++)
{
P[i]=&F[i][0];
}
outfile<<solve(P,n,a,b);
infile.close();
outfile.close();
return 0;
}

4、算法的时间分析
在solve函数中,使用for循环遍历所有任务,使用双重for循环遍历A所需要的所有时间,时间复杂度为O(n*sum)。
在main函数中,使用for循环对a[n ],b[n]数组赋值,再调用solve函数,时间复杂度为O(n2)。
综上,时间复杂度为O(n2

四、总结分析:
动态规划解题的一般思路:
1. 将原问题分解为子问题
把原问题分解为若干个子问题,子问题和原问题形式相同或类似,只不过规模变小了。子问题都解决,原问题即解决。
子问题的解一旦求出就会被保存,所以每个子问题只需求解一次。
2.确定状态
在用动态规划解题时,我们往往将和子问题相关的各个变量的一组取值,称之为一个“状 态”。一个“状态”对应于一个或多个子问题, 所谓某个“状态”下的“值”,就是这个“状 态”所对应的子问题的解。
所有“状态”的集合,构成问题的“状态空间”。“状态空间”的大小,与用动态规划解决问题的时间复杂度直接相关。 在数字三角形的例子里,一共有N×(N+1)/2个数字,所以这个问题的状态空间里一共就有N×(N+1)/2个状态。
整个问题的时间复杂度是状态数目乘以计算每个状态所需时间。在数字三角形里每个“状态”只需要经过一次,且在每个状态上作计算所花的时间都是和N无关的常数。
3.确定一些初始状态(边界状态)的值
4. 确定状态转移方程
定义出什么是“状态”,以及在该“状态”下的“值”后,就要找出不同的状态之间如何迁移――即如何从一个或多个“值”已知的 “状态”,求出另一个“状态”的“值”(递推型)。状态的迁移可以用递推公式表示,此递推公式也可被称作“状态转移方程”。

  • 11
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值