【回溯法】批处理作业调度问题

给定n个作业的集合J=(J1,J2,…,Jn)。每一个作业Ji都有两项任务分别在2台机器上完成。每个作业必须先由机器1处理,然后再由机器2处理。作业Ji需要机器j的处理时间为tji;i=1,2,…n;j=1,2。对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时间。则所有作业在机器2上完成处理的时间和f=F21+F21+…+F2n成为该作业调度的完成时间和。

批处理作业调度问题要求对于给定的n个作业,制定最佳作业调度方案,使其完成时间和达到最小。

分析:批处理作业调度问题要从n个作业的所有排列中找出最小完成时间和的作业调度,所以批处理作业调度的解空间是一颗排列树。按照回溯法搜索排列树的算法框架,设开始时x=[1,2,…,n]是所给的n个作业,则相应的排列树由x[1:n]的所有排列构成。

递归回溯

#include <iostream>
using namespace std;

class Flowshop;
int Flow(int **,int, int []);

void Swap(int &a, int &b)
{
	int temp=a;
	a=b;
	b=temp;
}

class Flowshop
{
	friend int Flow(int **,int, int []);
private:
	void Backtrack(int i);
	int **M,		//各作业所需的处理时间
		*x,			//当前作业调度
		*bestx,		//当前最优作业调度
		*f2,		//机器2完成处理的时间
		f1,			//机器1完成处理的时间
		f,			//完成时间和
		bestf,		//当前最优值
		n;			//作业数
};

void Flowshop::Backtrack(int i)
{
	if(i>n)
	{//到达叶子结点
		for(int j=1; j<=n; ++j)
			bestx[j]=x[j];
		bestf = f;
	}else
		for(int j=i; j<=n; ++j)  // 因为问题的解空间是一颗由x[1:n]的所有排列构成的排列树
		{ // 所以第i次所调度的作业是从序号为i到n的作业中选择一个座位子树分支
			f1 += M[x[j]][1]; // +第i次所调度的作业在机器1上的处理时间
			f2[i] = ((f2[i-1]>f1) ? f2[i-1] : f1) + M[x[j]][2];
			f += f2[i];      //  +第i次所调度的作业在机器2上的处理时间
			if(f<bestf)
			{
				Swap(x[i], x[j]);
				Backtrack(i+1);
				Swap(x[i], x[j]);
			}
			f1 -= M[x[j]][1]; // -第i次所调度的作业在机器1上的处理时间
			f -= f2[i];       // -第i次所调度的作业在机器2上的处理时间
		}
}

int Flow(int **M, int n, int bestx[])
{
	int ub=INT_MAX;
	Flowshop X;
	X.x = new int[n+1];
	X.f2 = new int[n+1];
	X.M = M;
	X.n = n;
	X.bestx = bestx;
	X.bestf = ub;
	X.f1 = 0;
	X.f = 0;
	for(int i=0; i<=n; i++)
	{
		X.f2[i]=0;
		X.x[i]=i;
	}
	X.Backtrack(1);
	delete [] X.x;
	delete [] X.f2;
	return X.bestf;
}

int main(int argc, char *argv[])
{
	int **M = new int*[4];
	for(int i=0; i<=3; ++i)
		M[i] = new int[3];
	M[1][1] = 2; M[1][2]=1;
	M[2][1] = 3; M[2][2]=1;
	M[3][1] = 2; M[3][2]=3;
	int *bestx = new int[4];

	for(int m=1; m<=3; m++)
	{
		for(int n=1; n<=2; n++)
			cout << M[m][n] << " ";
		cout << endl;
	}

	cout << Flow(M, 3, bestx) << endl;
	for(int i=1; i<=3; ++i)
		cout << bestx[i] << ",";

	cout << "Press the enter key to exit";
	cin.ignore(cin.rdbuf()->in_avail()+1);
	return 0;
}

    原文作者:回溯法
    原文地址: https://blog.csdn.net/yuanyu5237/article/details/6595305
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞