天天看點

有一個流水作業排程問題,n=4,a[]={5,10,9,7},b[]={7,5,9,8},請實作基于優先隊列的分枝限界算法進行求解。

#問題:

有一個流水作業排程問題,n=4,a[]={5,10,9,7},b[]={7,5,9,8},請實作基于優先隊列的分枝限界算法進行求解。
           

##源代碼:

//有一個流水作業排程問題,n=4,a[]={5,10,9,7},b[]={7,5,9,8},請實作基于優先隊列的分枝限界算法進行求解。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define INF 999999
#define	MAX 5

using namespace std;

//問題表示
int n = 4; //作業數
int a[MAX] = { 0,5,10,9,7 };//M1上的執行時間,不用下标0的元素
int b[MAX] = { 0,7,5,9,8 };//M2上的執行時間,不用下标0的元素
//求解結果表示
int bestf = INF;//存放最優排程時間
int bestx[MAX];//存放目前作業最佳排程
int total = 1;//結點個數累計

struct NodeType//隊列結點類型
{
    int no;//結點編号
    int x[MAX];//x[i]表示第i步配置設定作業編号
    int y[MAX];//y[i]=1表示編号為i的作業已經配置設定
    int i;//步驟編号
    int f1;//已經配置設定作業M1的執行時間
    int f2;//已經配置設定作業M2的執行時間
    int lb;//下界
    bool operator<(const NodeType& s) const//重載<關系函數
    {
        return lb > s.lb;//lb越小越優先出隊
    }
};

void bound(NodeType& e)//求結點e的限界值
{
    int sum = 0;
    for (int i = 1; i <= n; i++)//掃描所有作業
    {
        if (e.y[i] == 0)
        {
            sum += b[i];//僅累計e.x中還沒有配置設定的作業的b時間
        }
    }
    e.lb = e.f1 + sum;
}

void bfs()//求解流水作業排程問題
{
    NodeType e, e1; priority_queue<NodeType> qu;//定義優先隊列
    memset(e.x, 0, sizeof(e.x));//初始化根結點的x
    memset(e.y, 0, sizeof(e.y));//初始化根結點的y
    e.i = 0;//根結點
    e.f1 = 0;
    e.f2 = 0;
    bound(e);
    e.no = total++;
    qu.push(e);//根結點進隊列
    while (!qu.empty())
    {
        e = qu.top();
        qu.pop(); //出隊結點e
        if (e.i == n) //達到葉子結點
        {
            if (e.f2 < bestf) //比較求最優解
            {
                bestf = e.f2;
                for (int j1 = 1; j1 <= n; j1++)
                {
                    bestx[j1] = e.x[j1];
                }
            }
        }
        e1.i = e.i + 1;//擴充配置設定下一個步驟的作業,對應結點e1
        for (int j = 1; j <= n; j++)//考慮所有的n個作業
        {
            if (e.y[j] == 1)
            {
                continue;//作業j是否已配置設定,若已配置設定,跳過
            }
            for (int i1 = 1; i1 <= n; i1++)//複制e.x得到e1.x
            {
                e1.x[i1] = e.x[i1];
            }
            for (int i2 = 1; i2 <= n; i2++)//複制e.y得到e1.y
            {
                e1.y[i2] = e.y[i2];
            }
            e1.x[e1.i] = j;//為第i步配置設定作業j
            e1.y[j] = 1;//表示作業j已經配置設定
            e1.f1 = e.f1 + a[j];//求f1=f1+a[j]
            e1.f2 = max(e.f2, e1.f1) + b[j];//求f[i+1]=max(f2[i],f1)+b[j]
            bound(e1);
            if (e1.f2 <= bestf)//剪枝,剪去不可能得到更優解的結點
            {
                e1.no = total++;//結點編号增加1
                qu.push(e1);
            }
        }
    }
}

int main()
{
    bfs();
    cout << "Optimal plan is :" << endl;
    for (int k = 1; k <= n; k++)
    {
        cout << "The " << k << " step is to execute the job is :" << bestx[k] << endl;
    }
    cout << "The total time is :" << bestf << endl;
    cout << "Ahui nb Ahui nb!";
    return 0;
}


           

繼續閱讀