問題的描述:
汽車生產工廠共有兩條裝配線,每條有 n 個裝配站;裝配線 i 的第 j 個裝配 站表示為 Si,j,在該站的裝配時間為 ai,j。一個汽車底盤進入工廠,然後進入裝配 線 i(i 為 1 或 2) ,花費時間為 ei。在通過一條線的第 j 個裝配站後,這個底盤來 到任一條線的第(j+1)個裝配站。如果它留在相同的裝配線,則沒有移動開銷; 如果它移動到另一條線上,則花費時間為 ti,j。在離開一條線的第 n 個裝配站後, 完成的汽車花費時間 xi 離開工廠。帶求解的問題是:確定應該在裝配線 1 內選擇 哪些站,在裝配線
2 內選擇哪些站,才能使汽車通過工廠的總時間最小。
動態規劃的解題步驟有四步:
步驟1:描述最優解的結構的特徵 .
步驟2:利用子問題的最優解來遞迴定義一個最優解的值
步驟3:計算最快時間
步驟4:構造通過工廠的最快路線
在這之前先說明要用到的一些符號的定義:
進入每條裝配線的時間存在數組e[]中
出每條裝配線的時間存放在數組x[]中
每條裝配線的每個裝配站的時間存放在數組a[2][n]中,a[1][4]就代表第2條裝配線的第5個裝配站。
從一條裝配線的某一個裝配站,到另一條裝配線的下一個裝配站的時間,存放在數組t[2][n]中,
例如,t[0][4]就代表從第一條裝配線的第五個裝配站轉移到第二條裝配線的第六個裝配站的時間。
計算最短時間的過程中,用數組f[2][n]儲存過程的中間解。例如,f[1][3]就儲存了到達第二條
裝配線的第四個裝配站的最短時間。然後用min_f儲存最終的結果,也就是最短的生產時間。
為了輸出整條最短時間的生產裝配站序列,再設一個數組L[2][n],其中L[1][5]就表示到達第二條裝配
線的第六個裝配站的前一個裝配站,也就是第五個裝配站是屬於哪一條裝配線的,是1還是2.然後
fin_l儲存最終產生完成時,是從哪一條裝配線出來的。
最終我們要求的結果就是min_f(就是下面圖中的f*),經過工廠n個裝配站的最短時間
公式表達的很清晰,這個公式就是用上面提到的最優解結構的求法定義出來的。
根據遞迴的定義以及上面的內容,也可以得出要求出到達每一個裝配站的最優時間的遞迴公式
這樣就可以求出最終的min_f了,也就是第三步的計算最優解的值就出來了。因為還有第四步,就是構造最優解,在這道題目中,就是要構造出這條時間花費最小的路線。為了可以構造出這條路線,還要記錄下到達每一個裝配站時,上一個裝配站是屬於哪一條裝配線的,也就是上面的數組L[2][n]的定義。
下面是代碼,資料是按照下面這張圖輸入的
#include <iostream>#include <stack>using namespace std;void pr_minLine(int l[][6],int n,int fin_l){stack<int> s;int i=fin_l;s.push(i);for(int j=n-1;j>=1;--j){i=l[i][j];s.push(i);}for(int j=0;j<n;++j){cout << "line " << s.top()+1<< " station: " << j+1 << endl;s.pop();}}int fastWay(int a[][6],int t[][6],int e[],int x[],int f[][6],int l[][6],int n){int fin_l,min_f;f[0][0]=e[0]+a[0][0];f[1][0]=e[1]+a[1][0];for(int i=1;i<n;++i){if( f[0][i-1]+ a[0][i] <= f[1][i-1] +t[1][i-1]+ a[0][i] ){f[0][i]=f[0][i-1]+ a[0][i] ;l[0][i]=0;}else{f[0][i] = f[1][i-1] +t[1][i-1]+ a[0][i];l[0][i] = 1;}if (f[1][i - 1] + a[1][i] <= f[0][i - 1] + t[0][i - 1] + a[1][i]){f[1][i] = f[1][i - 1] + a[1][i];l[1][i] = 1;}else{f[1][i] = f[0][i - 1] + t[0][i - 1] + a[1][i];l[1][i] = 0;}}min_f= f[0][n-1] + x[0] <= f[1][n-1] + x[1] ? (fin_l=0,f[0][n-1] + x[0]) : (fin_l=1,f[1][n-1] + x[1]);pr_minLine(l,n,fin_l);return min_f;}int main() {int a[2][6]={{7,9,3,4,8,4},{8,5,6,4,5,7}};int t[2][6]={{2,3,1,3,4},{2,1,2,2,1}};int e[2]={2,4};int x[2]={3,2};// f[i][j] 表示到第i條線的第j個站,最小要花多長時間// l[i][j] 表示到第i條線的第j個站,是從哪個哪條線進來的// fin_l 表示最後是從哪條線出來的int f[2][6],l[2][6];cout << "\n最短時間:" << fastWay(a,t,e,x,f,l,6) << endl;return 0;}