動態規劃——裝配線調度問題

一、問題描述

        裝配線調度問題如下:

        Colonel汽車公司在有兩條裝配線的工廠內生產汽車,一個汽車底盤在進入每一條裝配線後,在每個裝配站會在汽車底盤上安裝不同的部件,最後完成的汽車從裝配線的末端離開。如下圖1所示。


圖1 裝配線示意圖

        每一條裝配線上有n個裝配站,編號爲j=1,2,...,n,將裝配線i(i爲1或2)的第j個裝配站表示爲S(i,j)。裝配線1的第j個站S(1,j)和裝配線2的第j個站S(2,j)執行相同的功能。然而這些裝配站是在不同的時間建造的,並且採用了不同的技術,因此,每個站上完成裝配所需要的時間也不相同,即使是在兩條裝配線上相同位置的裝配站也是這樣。把每個裝配站上所需要的裝配時間記爲a(i,j),並且,底盤進入裝配線i需要的時間爲e(i),離開裝配線i需要的時間是x(i)。正常情況下,底盤從一條裝配線的上一個站移到下一個站所花費的時間可以忽略,但是偶爾也會將未完成的底盤從一條裝配線的一個站移到另一條裝配線的下一站,比如遇到緊急訂單的時候。假設將已經通過裝配站S(i,j)的底盤從裝配線i移走到另一條裝配線所花費的時間爲t(i,j),現在的問題是要確定在裝配線1內選擇哪些站以及在裝配線2內選擇哪些站,以使汽車通過工廠的總時間最小。

二、問題分析

        初看該問題,最簡單的解決方案就是遍歷法,在遍歷的過程中得出最小時間。但應當看到,當站點數n較大時,需要遍歷2的n次方條路線,效率是較低的。那麼,有沒有效率更高的解決方案呢?

        爲了方便分析問題,我們爲該問題建立一個簡單的數學模型。假設通過裝配站j的最短總時間爲f(j),通過裝配站j的最短路線選擇的裝配線是r(j)(r(j)的值爲1或2),則汽車通過工廠的總時間爲f=f(n)+x(r(n)),其中x(r(n))爲離開裝配線r(n)的需要的時間。那麼,現在關鍵的問題就是要計算出f(n)和r(n)。汽車通過裝配站n的路線中也必然通過了裝配站n-1,如果計算出了f(n-1)和r(n-1),則f(n)就是f(n-1)加上從第n-1個裝配站到第n個裝配站的最短時間。而知道了r(n-1),計算從第n-1個裝配站到第n個裝配站的最短時間是非常容易的,記!r(j)爲另一條裝配線,則只需要找出a(r(n-1),n)和a(!r(n-1),n)+t(r(n-1), n-1)中的較小值即可。

        根據上面的分析,可以得出:

        f(n)=f(n-1)+min(a(r(n-1),n),a(!r(n-1),n)+t(r(n-1), n-1))

        r(n)=r(n-1) 如果a(r(n-1),n) <=a(!r(n-1),n)+t(r(n-1), n-1)

                !r(n-1) 如果a(r(n-1),n) > a(!r(n-1),n)+t(r(n-1), n-1)

        更一般地,我們可以得出:

        f(1)=min(e1+a(1,1), e2+a(2, 1))

        r(1)=1 如果e1+a(1,1) <=e2+a(2, 1)

                2 如果e1+a(1,1) >e2+a(2, 1)

        f(j)=f(j-1)+min(a(r(j-1),n),a(!r(j-1),n)+t(r(j-1), j-1)) 其中2=<j<=n

        r(j)=r(j-1) 如果a(r(j-1),j) <=a(!r(j-1),j)+t(r(j-1), j-1)

               !r(j-1)  如果a(r(j-1),j) > a(!r(j-1),j)+t(r(j-1), j-1)

        有了上面的遞推式,我們就可以採用自底向上的方式計算出汽車通過工廠的最短時間和採用的具體路線。

三、程序實現

        下面是我寫的解決裝配線調度的程序:

#include <iostream>
#include <vector>
using namespace std;

double f(int stationNo, int &lineNo, const vector<double> &duaration1, const vector<double> &duaration2, const vector<double> &line1to2, const vector<double> &line2to1, const double &in1, const double &in2);

int main()
{
	// 默認進入和出來的花費爲時間1,轉移需要花費的時間也都爲1,每條裝配線每個站需要的時間爲下面兩個數組所示,則正確調度序列應該爲:2,1,2,總時間應該爲10
	double dTemp1[] = {2, 1, 6};
	double dTemp2[] = {1, 3, 4};
	size_t size = sizeof(dTemp1) / sizeof(double);
	vector<double> duaration1(dTemp1, dTemp2 + size), // 第一條裝配線每個站需要花費的時間
	duaration2(dTemp2, dTemp2 + size), // 第二條裝配線每個站需要花費的時間
	line1to2(2, 1), // 從第一條裝配線移動到第二條裝配線需要的時間,假設都爲1
	line2to1(2, 1); // 從第二條裝配線移動到第一條裝配線需要的時間,假設都爲1

	double in1 = 1.0, in2 = 1.0, out1 = 1.0, out2 = 1.0; // 進入和離開的時間,假設都爲1
	int lineNo = 0; // 最後從哪條裝配線出來
	double totalTime = f(size - 1, lineNo, duaration1, duaration2, line1to2, line2to1, in1, in2);
	if (lineNo == 1)
		totalTime += out1;
	else
		totalTime += out2;
	cout << "Total time " << totalTime << endl;
	
	return 0;
}

double f(int stationNo, int &lineNo, const vector<double> &duaration1, const vector<double> &duaration2, const vector<double> &line1to2, const vector<double> &line2to1, const double &in1, const double &in2)
{
	if (stationNo == 0)
	{
		double time = 0.0;
		double time1 = in1 + duaration1.at(0);
		double time2 = in2 + duaration2.at(0);
		time = (time1 <= time2) ? time1 : time2;
		lineNo = (time1 <= time2) ? 1 : 2;
		cout << "station " << stationNo + 1 << " produced at line " << lineNo << endl;
		return time;
	}

	double previousTime = f(stationNo - 1, lineNo, duaration1, duaration2, line1to2, line2to1, in1, in2); // f(n-1)花費的時間
	double stationNoTime = 0.0; // 本站需要花費的時間
	if (lineNo == 1) // 之前的作業在第一條裝配線完成
	{
		stationNoTime = duaration1.at(stationNo);
		double toLine2Time = duaration2.at(stationNo) + line1to2.at(stationNo - 1);
		if (stationNoTime > toLine2Time)
		{
			stationNoTime = toLine2Time;
			lineNo = 2;
		}
	} 
	else if (lineNo == 2) // 之前的作業在第二條裝配線完成
	{
		stationNoTime = duaration2.at(stationNo);	
		double toLine1Time = duaration1.at(stationNo) + line2to1.at(stationNo - 1);
		if (stationNoTime > toLine1Time)
		{
			stationNoTime = toLine1Time;
			lineNo = 1;
		}
	}
	cout << "station " << stationNo + 1 << " produced at line " << lineNo << endl;

	double totalTime = stationNoTime + previousTime;

	return totalTime;
}

        結果爲:

station 1 produced at line 2
station 2 produced at line 1
station 3 produced at line 2
Total time 10

        結果正確。

       本文轉載自:http://www.cnblogs.com/hujian/archive/2012/03/14/2396565.html,略做修改。

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