分支限界批处理的算法

来源:互联网 发布:倾斜摄影测量软件 编辑:程序博客网 时间:2024/05/17 06:04

#include <iostream>
#include <stdio.h>
#include <time.h> // 用time() 得到种子
#include <queue> // 用到里面的优先队列(priority_queue)
using namespace std;

const int N = 8; // 作业数
const int TIME = 99; // 每个作业的时间控制在两位数内
const int NUM = 50; // 测试次数

class Flowshop1 {
private:
      int **M,      // 各作业所需的处理时间
            n;        // 作业数
      int *bestx, // 当前最优作业调度
            *x,       // 当前作业调度
            *f2,      // 机器完成处理时间
            f1,       // 机器完成处理时间
            f,        // 完成时间和
            bestf;  // 当前最优值
      void Backtrack(int i);
      void Swap(int &x, int &y);
public:
      Flowshop1(int **M, int n);
      ~Flowshop1();
      int getBestf();
      int *getBestx();
};

struct MinHeapNode {
      int s,     // 已经安装的作业数
            f1,  // 机器上最后完成时间
            f2,  // 机器上最后完成时间
            sf2, // 当前机器上的完成时间和
            bb,  // 当前完成时间和下界
            *x;  // 当前作业调度
      MinHeapNode(int n) {
            x = new int[n];
            for (int i=0; i<n; i++) x[i] = i;
            s = f1 = f2 = sf2 = bb = 0;
      }
      // (E, 机器上最后完成时间, 机器上最后完成时间, 当前完成时间和下界, n)
      MinHeapNode(MinHeapNode &E, int Ef1, int Ef2, int Ebb, int n) {
            x = new int[n];
            for (int i=0; i<n; i++) x[i] = E.x[i];
            f1 = Ef1;
            f2 = Ef2;
            sf2 = E.sf2 + f2;
            bb = Ebb;
            s = E.s + 1;
      }
      //~MinHeapNode() { delete []x; }
};

struct cmp {
      bool operator() (const MinHeapNode &a, const MinHeapNode &b) {
          return (a.bb > b.bb);
      }
};

class Flowshop2 {
private:
      int n,        // 作业数
            **M;      // 各作业所需的处理时间
      int **b,      // 各作业所需的处理时间排序数组
            **a,      // 数组M和b的对应关系数组
            *bestx, // 最优解
            bestc;  // 最小完成时间和
      void BBFlow(void);
      int Bound(MinHeapNode &E, int &f1, int &f2);
      void Sort(void);
      void Swap(int &x, int &y);
public:
      Flowshop2(int **M, int n);
      ~Flowshop2();
      int getBestf();
      int *getBestx();
};

int main()
{

      int *M[N], i;
     
      srand(time(0));
      for (int num=1; num<=NUM; num++)
      {
            for (i=0; i<N; i++)
            {
                  M[i] = new int[2];
                  M[i][0] = rand() % TIME + 1;
                  M[i][1] = rand() % TIME + 1;
            }
           
            Flowshop1 *my1 = new Flowshop1(M, N);
            Flowshop2 *my2 = new Flowshop2(M, N);
           
            printf("/n [%d]/t%d/t%d/n", num, my1->getBestf(), my2->getBestf());
            for (i=0, putchar('/t'); i<N; i++) printf("--------");
            putchar('/n');
            if (my1->getBestf() != my2->getBestf()) {
                  printf("/tNot Equal ");
                  getchar(); // 最优值不等(表示程序有错),等待...
            }
           
            for (i=0; i<N; i++) printf("/t%d", my1->getBestx()[i]);
            putchar('/n');
            for (i=0; i<N; i++) printf("/t%d", my2->getBestx()[i]);
            putchar('/n');
            for (i=0; i<N; i++) {
                  if (my1->getBestx()[i] != my2->getBestx()[i]) {
                        putchar(7); // 最优作业调度方案不一样,响铃(允许不一样)
                        break;
                  }
            }
           
            delete my1;
            delete my2;
      }
     
      for (i=0; i<N; i++) delete []M[i];
   char zyg;
   cout <<"按任意键继续"<< endl ;
   cin.get(zyg) ;
      return 0;
}

Flowshop1::Flowshop1(int **M, int n)
{
      this->M = M;
      this->n = n;
      this->bestx = new int[n];
      this->x = new int[n];
      this->f2 = new int[n];
      this->f1 = 0;
      this->f = 0;
      this->bestf = (~(unsigned int)0) >> 1;
      for (int i=0; i<n; i++) this->x[i] = i;
      this->Backtrack(0);
}

Flowshop1::~Flowshop1()
{
      delete []bestx;
      delete []x;
      delete []f2;
}

int Flowshop1::getBestf()
{
      return bestf;
}

int *Flowshop1::getBestx()
{
      return bestx;
}

void Flowshop1::Backtrack(int i)
{
      if (i == n) {
            for (int j=0; j<n; j++)
                  bestx[j] = x[j];
            bestf = f;
      }
      else {
            for (int j=i; j<n; j++) {
                  if (i == 0) {
                        f1 = M[x[j]][0];
                        f2[i] = f1 + M[x[j]][1];
                        f = f2[i];
                  }
                  else {
                        f1 += M[x[j]][0];
                        f2[i] = ((f2[i - 1] > f1) ? f2[i - 1] : f1) + M[x[j]][1];
                        f += f2[i];
                  }
                  if (f < bestf) {
                        Swap(x[i], x[j]);
                        Backtrack(i + 1);
                        Swap(x[i], x[j]);
                  }
                  f1 -= M[x[j]][0];
                  f -= f2[i];
            }
      }
}

void Flowshop1::Swap(int &x, int &y)
{
      int temp = x;
      x = y;
      y = temp;
}

Flowshop2::Flowshop2(int **M, int n)
{
      this->M = M;
      this->n = n;
      b = new int *[n];  // 各作业所需的处理时间排序数组
      a = new int *[n];  // 数组M和b的对应关系数组
      bestc = (~(unsigned int)0) >> 1; // 最小完成时间和
      for (int i=0; i<n; i++) {
            a[i] = new int[2];
            b[i] = new int[2];
      }
      bestx = new int[n]; // 最优解
      this->Sort();
      this->BBFlow();
}

Flowshop2::~Flowshop2()
{
      for (int i=0; i<n; i++) {
            delete []a[i];
            delete []b[i];
      }
      delete []a;
      delete []b;
      delete []bestx;
}

int Flowshop2::getBestf()
{
      return bestc;
}

int *Flowshop2::getBestx()
{
      return bestx;
}

void Flowshop2::BBFlow(void)
{
      priority_queue<MinHeapNode, vector<MinHeapNode>, cmp> H;
     
      MinHeapNode E(n);
      while (true)
      {
            if (E.s == n) { // 叶结点
                  if (E.sf2 < bestc) {
                        bestc = E.sf2;
                        for (int i=0; i<n; i++) bestx[i] = E.x[i];
                  }
                  break;
            }
            else {
                  for (int i=E.s; i<n; i++) {
                        Swap(E.x[E.s], E.x[i]);
                        int f1, f2;
                        int bb = Bound(E, f1, f2);
                        if (bb < bestc) { // 子数可能含最优解
                              MinHeapNode N(E, f1, f2, bb, n);
                              H.push(N);
                        }
                        Swap(E.x[E.s], E.x[i]);
                  }
            }
            // 由于E被用于插入堆, 如果~MinHeapNode() { delete []x; }
            // 那么堆中对应的x将为黑指针, 只有在这里delete 才可以避免
            delete []E.x;
            if (H.empty()) {
                  printf("/tMin Heap Empty /n"); // 报错
                  break;
            }
            else {
                  E = H.top();
                  H.pop();
            }
      }
     
      while (!H.empty()) {
            delete []H.top().x;
            H.pop();
      }
}

int Flowshop2::Bound(MinHeapNode &E, int &f1, int &f2)
{ // 计算完成时间和下界
      int j, k;
      bool **y = new bool *[n]; // 工作数组
     
      for (k=0; k<n; k++) {
            y[k] = new bool[2];
            for (j=0; j<2; j++)
                  y[k][j] = false;
      }
      for (k=0; k<=E.s; k++) {
            for (j=0; j<2; j++)
                  y[a[E.x[k]][j]][j] = true; // 找到在b数组中对应的位置并赋值
      }
      f1 = E.f1 + M[E.x[E.s]][0];
      f2 = ((f1 > E.f2) ? f1 : E.f2) + M[E.x[E.s]][1];
      int sf2 = E.sf2 + f2;
     
      // 机器和机器的作业顺序不一样
      // 分别都先运行时间短的, 而假设其可以运行
      // s1: 假设机器很快很快
      // s2: 假设机器很快很快
      // 原则是使估计得到的下界尽可能的大
      int s1 = 0, k1 = n - E.s, f3;
      for (j=0; j<n; j++)
      {
            if (!y[j][0]) {
                  k1--;
                  if (k1 == n - E.s - 1) // 找到的第一个
                        f3 = (f2 > f1 + b[j][0]) ? f2 : f1 + b[j][0];
                  s1 += f1 + k1 * b[j][0]; // 假设作业在机器上顺序执行并无时间间隔
            }
      }
      int s2 = 0, k2 = n - E.s;
      for (j=0; j<n; j++)
      {
            if (!y[j][1]) {
                  k2--;
                  s1 += b[j][1]; // 加上时间间隔
                  s2 += f3 + k2 * b[j][1];
            }
      }
     
      for (j=0; j<n; j++) delete []y[j];
      delete []y;
      return sf2 + ((s1 > s2) ? s1 : s2);
}

void Flowshop2::Sort(void)
{ // 对各作业在机器和上所需时间排序
      int *c = new int[n];
      int i, j, k;
     
      for (j=0; j<2; j++) {
            for (i=0; i<n; i++) {
                  b[i][j] = M[i][j];
                  c[i] = i;
            }
            for (i=0; i<n-1; i++) {
                  for (k=n-1; k>i; k--) {
                        if (b[k - 1][j] > b[k][j]) { // 结果为从小到大
                              Swap(b[k - 1][j], b[k][j]);
                              Swap(c[k - 1], c[k]);
                        }
                  }
            }
            for (i=0; i<n; i++) a[c[i]][j] = i; // M对应元素在b数组中的位置
      }
      delete []c;
}

void Flowshop2::Swap(int &x, int &y)
{
      int temp = x;
      x = y;
      y = temp;

}

原创粉丝点击