最优批处理问题---动态规划

本文介绍了一种用于解决最优批处理问题的算法,针对n个作业分配任务,考虑启动时间、单独作业时间及费用,通过动态规划求解最小总费用的批处理方案。通过实例演示和状态转移方程,展示了如何计算m[i][begin]的最小值来优化作业调度。
摘要由CSDN通过智能技术生成

问题描述

在一台超级计算机上,编号为1,2,3···的n个作业等待批处理。批处理的任务就是将这n个作业分成若干批,每批包含相邻的若干作业。从时刻0开始,分批加工这些作业。在每批作业开始前,机器需要启动时间S,而完成这批作业所需的时间是单独完成批中各个作业需要时间的总和。单独完成第i个作业所需的时间是 ti,所需的费用是它的完成时刻乘以一个费用系数fi。同一批作业将在同一时刻完成。例如,如果在时刻 T 开始一批作业 x,x+1,x+2···x+k, 则这一批作业的完成时刻均为T+S+(tx+tx+1tx+2···+tk)。最优批处理问题就是要确定总费用最小的批处理方案。
例如,假定有5个作业等待批处理,且S=1,(t1,t2,t3,t4,t5)=(1,3,4,2,1),(f1,f2,f3,f4,f5)=(3,2,3,3,4)如果采用批处理方案(1,2),(3),(4,5),则各作业的完成时间分别为(5,5,10,14,14),各作业的费用分别为(15,10,30,42,56),因此这个批处理方案总费用是153
算法设计:
对于给定的待批处理的个作业,计算其总费用最小的批处理方案。
样例输入
5
1
1 3
3 2
4 3
2 3
1 4
样例输出
153
**

分析

设m[i][begin]表示从时间begin开始,处理第i~n个作业的最小总费用
例如对于1-5作业来说,m[3][5]就表示在时刻5时候,开始执行3~5的作业
而3~5可以有多种批处理手法,比如:{3}{4}{5}、{3}{4,5}、{3,4}{5}、{3,4}{5}
因此需要将这些情况都计算出来,取最小值
假设用j将3~5分为两部分,有两种分法:
1.j = 4,则将3~5分为{3}{4,5}两部分
2.j = 5,则将3~5分为{3,4}{5}两部分
设前一部分为第一批作业,后一部分则为第二批作业
先执行第一批作业
j = 4时,开始时间为begin,
结束时间为 Ti = begin+s+t3, Fi = f3, price1 = Ti * Fi + m[4][Ti];
m[4][Ti]就是 递归计算{4,5}的最小费用
j = 5时,开始时间为begin,
结束时间为 Ti = begin+s+t3+t4, Fi = f5, price2 = Ti * Fi + m[5][Ti];
通过上面的例子,可以得出以下状态转移方程

m[i][begin] = min{ Ti * Fi + m[j][Ti] }   (i<j<=n+1)
  Ti = begin + s + ti + t(i+1) + t(i+2) + ... + t(j-1);
  Fi = fi + f(i+1) + ... + f(j-1);

代码

#include<stdio.h>
void solve(int n,int s,int T[],int F[]){
 //计算总的时间,最优批处理的时间肯定不会超过这个总时间 
 int sum_time = 0;
 for(int i = 1; i <= n; i++) sum_time += T[i];
 sum_time += n*s;
 //初始化m状态数组 
 int m[n+1][sum_time+1];
 for(int i = 1; i <= n; i++){
  for(int begin = sum_time; begin >= 0; begin--)
   m[i][begin] = 99999;
 }
 
 for(int i = n; i > 0; i--){//从第n个作业开始倒序计算 
  for(int begin = sum_time; begin >= 0; begin--){//开始时间从最大的开始 
   
   int Ti = begin + s;//开始执行的时间 
   int Fi = 0;
   
   for(int j = i+1; j <= n+1; j++){//分别从j = i+1处到j = n处把[i:n]分为[i:j-1]和[j:n] 
    Fi += F[j-1];
    Ti += T[j-1];
    int price = Ti * Fi;
    if(j != n+1) price += m[j][Ti];//如果j = n+1,也就是说单独处理第i=n个作业,直接用Ti*Fi就好了,因为后面没有其他作业了 
    if(price < m[i][begin])//找出m[i][begin]的最小值 
     m[i][begin] = price;
   }
  }
 }
 printf("最小总费用为:%d",m[1][0]);
}
int main(){
 int n,s;
 scanf("%d",&n);
 scanf("%d",&s);
 int t[n+1],f[n+1];
 for(int i = 1; i <= n; i++){
  scanf("%d %d",&t[i],&f[i]);
 }
 solve(n,s,t,f);
 return 0;
}

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值