回溯法之批處理作業調度問題

問題描述

在這裏插入圖片描述

題目分析

這道題目也是一個比較經典的回溯法問題,但是這個問題和我們之前說的裝載問題
不同的是,這裏面的每一種作業我們都要安排,而不是找其中的子集,而裝載問題纔是一個找子集的問題。所以根據回溯法框架裏的內容,對於這種解空間中必須包含全部而不是找子集的情況,我們應該使用的解空間是排列樹。結構如下圖所示:

在這裏插入圖片描述我們可以將這些序列看成是在x=(1,2,3)的基礎上經過各種不同作業的兩兩交換而得到的不同調度方案。在回溯法的框架中我們也提到了,解空間爲排列樹的問題是通過不斷交換來進行選擇不同情況的,在回溯的時候還需要將二者交換回來。
在這裏面我們需要聲明一個f2的一維數組表示機器2完成的時間,f1表示機器1完成的時間,M是一個二維數組,表示所有作業的調度時間。f2之所以用數組表示,是因爲我們其實在過程中f2存儲的是機器1完成的時間+機器2完成的時間(因爲機器1完成之後機器2才能完成,所以可以統一存儲)。但是後一項作業的結束時間取決於上一項作業的結束時間,如果上一項還沒完成,則機器2一定被佔用着,當前工作也就不能完成,這都實現中的一些細節,等下我們會看到具體如何展開。可以看代碼中的註釋.

代碼

#include <iostream>
using namespace std;
class Flowshop()
{
    //參數是作業調度時間表,作業數和當前的做優調度
    friend Flow(int **,int,int []);
    private:
        void Backtrack(int i);//參數是現在要執行的作業次序,不是具體的哪個作業
        int **M,//各作業所需的處理時間
        int *x,//作業的調度
        int *bestx,//當前的最優作業調度
        int *f2,//機器2完成處理時間,這裏之所以聲明爲數組是因爲f2和i有關係,我們會記錄下某一工作結束後的完成時間儲存在f2[i]裏
        int f1,//機器1完成處理時間
        int f,//完成時間和
        int bestf,//當前最優值,
        int n;//作業數
};
void Flowshop::Backtrack(int i)
{
    if(i > n)
    //到達了葉節點,我們需要更新當前最優調度和最優值
    {
        for(int j = 1;j < n;j++)
        {
            bestx[j] = x[j];
        }
        bestf = f;
    }
    else
    {
        //這裏的重點是這個j
        //j表示的是具體的工作,而i是作業分量,即我們現在正在要做第i個作業,於是我們選擇作業j作爲第i個要進行的作業
        for(int j = i;j < n;j++)
        {
            //機器1完成時間我們只需要簡單進行加和
            f1 += M[x[j]][1];
            //機器2完成時間取決於上一個工作的完成時間,i-1不完成我們無法完成i
            f2[i] = ((f2[i-1] > f1) ? f2[i-1] : f1) + M[x[j]][2];
            f += f2[i];
            if(f < bestf)
            {
                swap(x[i],x[j]);
                Backtrack(i + 1);
                swap(x[i],x[j]);
            }
            f1 -= M[x[j]][1];
            f -= f2[i];
        }
    }
}
int Flow(int **M,int n,int bestx[])
{
    int ub = INT_MAX;
    Flowshop X;
    X.x = new int [n + 1];
    X.f2 = new int [n + 1];
    X.M = M;
    X.n = n;
    X.bestx = bestx;
    X.bestf = ub;
    X.f1 = 0;
    X.f = 0;
    for(int i = 0;i <= n;i++)
    {
        X.f2[i] = 0;
        X.x[i] = i;
    }
    X.Backtrack(1);
    delete[] X.x;
    delete[] X.f2;
    return X.bestf;
}

總結

由於這是一個排列樹解空間,所以我們的時間複雜應該爲O(n!)
(排列組合問題)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章