#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;
}