回溯法求最佳调度(简易实现)

一、 算法描述

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;
}
    原文作者:回溯法
    原文地址: https://blog.csdn.net/u014744118/article/details/46389531
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞