算法导论实验七_回溯法求最佳调度(简易实现)

一、 算法描述

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;

}

你可能感兴趣的:(C++,算法,算法导论)