问题描述
在一台超级计算机上,编号为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;
}