算法设计——批处理作业(回溯)

问题

在这里插入图片描述
(有点类似动归的流水作业哈)
就是求的时间不同
这里需要求的每个作业在机器二上完成时的时间和
如有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;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值