问题
(有点类似动归的流水作业哈)
就是求的时间不同
这里需要求的每个作业在机器二上完成时的时间和
如有3个作业
在机器一上的加工时间为2 3 2
在机器二上的加工时间为1 1 3
此时安排方法有3!种
1 2 3:时间为3+6+10=19
1 3 2:时间为3+7+8=18
2 1 3:时间为20
2 3 1:时间为21
3 1 2:时间为19
3 2 1:时间为19
此时我们求得方法为第二种,时间最少
分析
问题的解空间为排列树(因为每个作业都需要处理)
对于排列树,我们就可以用回溯的方法进行求解
通过迭代回溯得到一系列的数值,再进行判断比较即可得到最优值
在函数体内:
1.判断是否到达叶子结点,若到达则判断此时解是否更优,若是则更新
退出
2.循环,更换排序
①将机器一上的时间进行累加,因为机器二的时间是在机器一加工后。
②计算机器二上完成的时间,如果前一个作业完成前本作业的机器一已经完成那么本作业机器二完成的时间为前一个作业机器二完成的时间加上自身时间,如果前一个作业完成后本作业的机器一才完成那么本作业机器二完成的时间为本作业机器一完成的时间加上自身时间
③更新总时间
④如果总时间变小了,那么交换两作业顺序,继续递归
注意
交换后一定要交换回来
机器一的时间要恢复
总时间要恢复
代码实现
//不太会
//基于交换的排列树
#include<stdio.h>
#define N 100
int n;
int m[N][3]; //作业时间
int bt=10000;//最优解
int ct=0;//当前值
int x[N];//标记
int choose[N];//记录
int t2[N];//在m2上完成的时间
int t1;//在m1上完成的时间
void swap(int i,int j){
int t=x[i];
x[i]=x[j];
x[j]=t;
}
void backtrack(int i){
int j;
if(i>n){//叶子结点
if(bt>ct){//更新最优解
bt=ct;
for(j=1;j<=n;j++){
choose[j]=x[j];
}
}
return ;
}
for(j=i;j<=n;j++){
t1+=m[x[j]][1];//机器一完成时间
if(t2[i-1]>t1){//机器二时间
t2[i]=t2[i-1]+m[x[j]][2];
} else
t2[i]=t1+m[x[j]][2];
ct+=t2[i];
if(ct<bt){
swap(i,j);//交换
backtrack(i+1);//递归
swap(i,j); //恢复
}
t1-=m[x[j]][1];
ct-=t2[i];
}
}
int main()
{
int i;
printf("请输入作业数目:");
scanf("%d",&n);
printf("请输入各作业在两机器上加工的时间:\n");
for(i=1;i<=n;i++){
scanf("%d %d",&m[i][1],&m[i][2]);
x[i]=i;
}
backtrack(1);
printf("最短时间为:%d\n处理顺序为:",bt);
for(i=1;i<=n;i++){
printf("%d ",choose[i]);
}
return 0;
}