问题描述:
n个作业(1,2,…,n)要在两台机器上处理,每个作业必须先由机器1处理,然后再由机器2处理,机器1处理作业i所需时间为a1,机器2处理作业i所需时间为bj(1<=i<=n),批处理作业调度问题要求确定这n个作业的最优处理顺序,使得从第1个作业在机器1上处理开始,到最后一个作业在机器2上处理结束所需时间最少。
例:作业-机器时间关系表为
约束条件:
当前作业的执行时间和必须小于之前已选择序列时间和的最小值
解图:
图中limit为限制条件,real为完成当前作业执行时间和,当real>=limit则回溯。
完整代码:
#include<stdio.h>
const int INF=1000;
const int max_task=10; //最大任务数
int n; //任务数
int a[max_task][2]; //存储每个作业分别在机器1与机器2上的时间消耗
int result[max_task]; //存储排列树中的一条路径
int best_result[max_task]; //存储最优路径
int min=INF; //安排任务最小完成时间
int rop[max_task+1]; //每个深度对应遍历进度
int finish[max_task+1]; //每一层消耗时间和
void swap(int result[max_task],int best_result[max_task]) //复制数组
{
for(int i=0;i<n;i++)
best_result[i]=result[i];
}
void allot_task(int depth)
{
static bool visited[max_task]; //标记已安排任务
for(int i=rop[depth];i<n;i++)
{
if(!visited[i]) //寻找该层未访问节点
{
int f1=0; //在机器一上的完成时间
int f2=0; //在机器二上的完成时间
rop[depth]=i+1; //更新该层访问进度
visited[i]=true; //标记作业
result[depth-1]=i; //加入结果序列
for(int j=0;j<n;j++)
{
if(visited[j])
{
f1+=a[j][0];
}
}
f2=f1+a[i][1]; //该作业完成时间
if(f2<finish[depth-1]) //该序列执行到此作业消耗时间
f2=finish[depth-1];
finish[depth]=f2;
if(depth==n) //最后一个作业
{
if(f2<min)
{
min=f2;
swap(result,best_result); //保存最优序列
}
visited[i]=false;
rop[depth]=0;
return;
}
else if(depth<n)
{
if(f2>min)
{
visited[i]=false;
allot_task(depth-1); //回溯
}
else
{
allot_task(depth+1); //继续添加作业
}
}
}
visited[rop[depth]-1]=false; //跟换当前层次作业需要把之前作业解标记
}
visited[rop[depth]-1]=false;
rop[depth]=0;
return;
}
main()
{
printf("请输入任务数:");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
printf("作业%d分别在机器1与机器2上运行时间:",i+1);
scanf("%d %d",&a[i][0],&a[i][1]);
}
allot_task(1);
printf("最优调度序列为:");
for(int i=0;i<n;i++)
{
printf("%d ",best_result[i]+1);
}
printf("\n消耗时间为:%d\n",min);
}
运行结果: