题目描述
用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行是1个正整数n<=200, 表示要处理n个作业。 接下来的2行中,每行有n 个
正整数,分别表示处理机A 和B 处理第i 个作业需要的处理时间。
输出
最短处理时间
样例输入
6
2 5 7 10 5 2
3 8 4 11 3 4
样例输出
15
思路:
- 这是一道动态规划的题,动态规划就是把i的题变为i-1的题来做。对于每个任务,我们要做的就是判断选A还是选B,如果只有一个任务,我们就很容易判断,如果有2个任务就在1最优的情况下进行判断。
- 对于所有任务来说,A做的越多、B就做的越少。B做的越多、A就做的越少。但最终时间还是要以做的多的那台为准。
- 每个任务都有不同选择,可能前i个任务的最优选择,到了第i+1个就不是最优了,所以我们要把前i个任务的每种可能找出来,再做i+1的判断
定义变量:
采用填表格的方式来做:
表格 form[i][j]: 表示第i个任务、j表示i个任务时给A的任务时间、每个表格中的值表示在第i个任务时,如果给A的时间为j的情况下,B的最少工作时间
- (也就是把A的工作时间当作已知的,B的工作时间是未知的。因为如果A做得多,那么B就做得少。所以当A的时间不一样时,B的时间也会不一样,我们就找出 每个不同A的时间 所对应的 B的时间)
atime[i]-操作i在机器A上的时间
btime[i]-操作i在机器B上的时间
-
因为 i 代表第几个任务,所以i的范围是0~num(num为总的任务个数)
-
j代表A的工作时间,如果全给A做那么A的工作时间为atime中每个值相加的和suma;如果全给B做,那A的时间为0,所以j的范围是0~suma。j代表给A的工作时间,意思就是在j时间内:A可以做、可以不做、做不完也可以。比如:两个任务,A的时间是3、5,所以j的范围是0-8,但当j=4的时候,A肯定不可能把这4分钟做满;
-所以j不带表A把这j分钟做满了,就只是给了A j分钟
判断方法:
再强调一下,表中的每个值代表的是B的时间,A的时间当作已知的,就是j。A时间越多B时间越少、B时间越多A时间越少
在第i个任务时给A的时间为j,A可能能完成,也可能完不成,因此分为两种情况:
-
j<A[i]时 : 就是j分钟内A无法完成任务i,所以任务i就只能给B做,此时的form[i][j]=form[i-1][j]+b[i]。因为A没有做任务i,B做的任务i,所以A在任务i-1时与在任务i时的时间是一样的,A在任务i-1时的时间是j,到了任务i时A的时间还是j;在任务i-1时B的工作时间为form[i-1][j],所以在form[i][j]时的时间为任务i-1时B的工作时间+做任务i B需要的时间,也就是form[i][j]=form[i-1][j]+b[i]
-
j>=A[i]时 ,即j时间内A能完成任务i,此时form[i][j]=min(form[i-1][j-a[i]],form[i-1][j]+b[i])
就是A做与B做情况下 那个B的工作时间最短,就将此时B的工作时间设为哪个。
- 如果选A来做任务i,那么A是做完任务i工作时间才到达j的,而B没有做任务i,B的时间没有变。所以在任务i,A工作时间为j时B的工作时间与在任务i-1、A工作时间为j-atime[i]时的B工作时间一样,
即form[i][j]=form[i-1][j-atime[i]] - 如果选B来做任务i, 那么任务i时,A的工作时间不会变,也就是是任务i之前任务i-1时A的工作时间就是j了。而B的时间会增加,也就是在任务i-1、A时间为j时的时间form[i-1][j]加上做任务i的时间btime[i],即:form[i][j]=form[i-1][j]+btime[i]
- 因为form[i-1][i-atime]时 A的工作时间 比 form[i-1][j]时A的工作时间少,所以form[i-1][i-atime]时B的工作时间比 form[i-1][j]时B的工作时间多,
- 而btime[i] 的多少也 不确定 所以要从 form[i-1][j-a[i]] 和 form[i-1][j]+b[i]选一个最小的时间。(再提醒一下,form中记录的是B的时间)
实例:
num = 5
atime={2、1、3、3、1},btime={3、2、1、2、2},suma=2+1+3+3+1=10
-
当i=0时,没有任务,所以不管A的工作时间为多少,B都不需要做什么,所以B的工作时间都为0
-
在i=1时
form[1][0]: j=0<atime[1]=2,所以任务给B做,form[1][0]=form[1-1][0]+btime[1]=0+3=3form[1][1]:j=1<atime[1]=2,所以任务给B做,form[1][0]=form[1-1][0]+btime[1]=0+3=3
form[1][2]:j=2=atime[1],所以form[1][2] = min((form[1-1][j]+btime[1]),form[1-1][j-atime[1]]),form[1-1][2]+btime[1]=3,form[1-1][2-atime[1]]=0,所以form[1][2]=form[1-1][2-atime[1]]=0=0
… -
在i=2时
form[2][0]: j=0<atime[2]=1,所以任务给B做,form[1][0]=form[2-1][0]+btime[2]=3+2=5 -
form[2][1]:j=1=atime[2],form[2-1][1]+btime[2]=3+2=5,form[2-1][1-atime[2]]=3,所以form[2][1]=form[2-1][1-atime[2]]=3
-
form[2][2]:j=2>atime[2],form[2-1][2]+btime[2]=0+2=2,form[2-1][2-atime[2]]=3,所以form[2][1]=form[2-1][2]+btime[2]=0+2=2
…
…
之后的以此类推
#include<iostream>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
using namespace std;
int atime[201],btime[201]; //如果为200就会RE
int form[201][10000];
int main()
{
int num,suma=0;
cin >> num;
for(int i =1;i<=num;i++)
{
cin >> atime[i];
suma += atime[i];
}
for(int i =1;i<=num;i++)
cin >> btime[i];
for(int i=1;i<=num;i++)
{
for(int j=0;j<=suma;j++)
{
if(atime[i]>j) //j时间内a无法完成任务i
{
form[i][j] = form[i-1][j]+btime[i];//处于任务i,a工作时间为j时状态下b的工作时间
}
else
{
form[i][j] = min((form[i-1][j]+btime[i]),form[i-1][j-atime[i]]);
}
}
}
int ans = 99999;
for(int i=0;i<=suma;i++)
{
int h=max(i,form[num][i]);
ans = min(ans,h);
//ans = min(ans,max(i,form[num][i])); //宏定义不能复合使用
}
cout << ans <<endl;
return 0;
}