一、 算法描述
void BackTrace(int k)//回溯算法描述
{
if (k>number)
{
for (int i=1;i<=number;i++)
{
bestOrder[i]=xOrder[i];
}
bestValue=xValue;
}
else
{
for (int i=k;i<=number;i++)
{
f1+=x1[xOrder[i]];
f2[k]=(f2[k-1]>f1?f2[k-1]:f1)+x2[xOrder[i]];
xValue+=f2[k];
swap(xOrder[i],xOrder[k]);
if (xValue<bestValue)
{
BackTrace(k+1);
}
swap(xOrder[i],xOrder[k]);
xValue-=f2[k];
f1-=x1[xOrder[i]];
}
}
}
二、 算法分析
回溯法,也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进, 不能进则退回来,换一条路再试。用回溯算法解决问题的一般步骤为:
1、定义一个解空间,它包含问题的解。
2、利用适于搜索的方法组织解空间。
3、利用深度优先法搜索解空间。
4、利用限界函数避免移动到不可能产生解的子空间。
问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的 所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯 定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。
回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。 这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。
输入:
1.任务数number
2.机器数M (2)
3.随机序列长度t[i],其中t[i]=x表示第i个任务完成需要时间单位x,
输出:
1.开销时间besttime,表示最佳调度需要时间单位
2.最佳调度序列bestx[],其中bestx[i]=x,表示将第i个任务分配给第x个机
器执行。
基本思路:
搜索从开始结点(根结点)出发,以DFS搜索整个解空间。每搜索完一条路径则记录下besttime 和bestx[]序列,开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处向纵深方向移至一个新结点,并成为一个新的活结点,也成 为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向扩展,则当前扩展结点就成为死结点。此时,应往回移动(回溯)至最近的一个活结点处,并使这个活 结点成为当前的扩展结点;直至找到一个解或全部解。
三、算法实现
#include <iostream>
#include <time.h>
using namespace std;
#define MAX 20000
int* x1;//作业在机器1上的工作时间;
int* x2;//作业在机器2上的工作时间;
int number=0;//作业的数目;
int* xOrder;//作业顺序;
int* bestOrder;//最优的作业顺序;
int bestValue=MAX;//最优的时间;
int xValue=0;//当前完成用的时间;
int f1=0;//机器1完成的处理时间;
int* f2;//第i阶段机器2完成的时间;
void BackTrace(int k)
{
if (k>number)
{
for (int i=1;i<=number;i++)
{
bestOrder[i]=xOrder[i];
}
bestValue=xValue;
}
else
{
for (int i=k;i<=number;i++)
{
f1+=x1[xOrder[i]];
f2[k]=(f2[k-1]>f1?f2[k-1]:f1)+x2[xOrder[i]];
xValue+=f2[k];
swap(xOrder[i],xOrder[k]);
if (xValue<bestValue)
{
BackTrace(k+1);
}
swap(xOrder[i],xOrder[k]);
xValue-=f2[k];
f1-=x1[xOrder[i]];
}
}
}
int main()
{
cout<<"请输入作业数目:";
cin>>number;
x1=new int[number+1];
x2=new int[number+1];
xOrder=new int[number+1];
bestOrder=new int[number+1];
f2=new int[number+1];
x1[0]=0;
x2[0]=0;
xOrder[0]=0;
bestOrder[0]=0;
f2[0]=0;
int i;
srand((unsigned)time(NULL));
cout<<"每个作业在机器1上所用的时间:"<<endl;
for ( i=1;i<=number;i++)
{
x1[i]=rand()%1000;
cout<<"第"<<i<<"个作业="<<x1[i]<<endl;
}
cout<<"每个作业在机器2上所用的时间:"<<endl;
for (i=1;i<=number;i++)
{
x2[i]=rand()%1000;
cout<<"第"<<i<<"个作业="<<x2[i]<<endl;
}
for (i=1;i<=number;i++)
{
xOrder[i]=i;
}
BackTrace(1);
cout<<"最节省的时间为:"<<bestValue;
cout<<endl;
cout<<"对应的方案为:";
for (i=1;i<=number;i++)
{
cout<<bestOrder[i]<<" ";
}
delete [] x1;
delete [] x2;
delete [] xOrder;
delete [] bestOrder;
delete [] f2;
return 0;
}