动态规划 - 装配线调度问题
1?????????動態規劃介紹
動態規劃(dynamic programming)是運籌學的一個分支,是求解決策過程(decision process)最優化的數學方法。
動態規劃通常應用于最優化問題。此類問題可能有很多種可行解。每個解有一個解,而我們希望找出一個最優解(最大值或最小值)。
動態規劃算法的設計可分為如下4個步驟:
(1)描述最優解的結構;
(2)遞歸定義最優解的值;
(3)按自底向上的方式計算最優解的值;
(4)由計算出的結果構造一個最優解。
第1~3步構成問題的動態規劃解得基礎,第4步在只要求計算最優解的值時可以略去。如果的確做了第4步,則有時要在第3步的計算中記錄一些附加信息,要構造一個最優解變得容易。
?
2?????????裝配線調度問題描述
一個找出通過工廠裝配線的最快方式的制造問題。共有兩條裝配線,每一條裝配線上有n個裝配站,編號為j = 0, 1, … , n - 1。裝配線i(i = 0或1),在裝配站S[i][j]上所需的裝配時間記為a[i][j]。一個汽車底盤進入工廠,然后進入裝配線i的進入時間為e[i],在通過一條線的第j個裝配站后,這個底盤來到任一條線的第(j + 1)個裝配站。如果留在相同的裝配線上,則沒有移動的開銷;如果在裝配站S[i][j]后,它移動到了另一條線上,則花費時間t[i][j]。在離開一條線的第n個裝配站后,完成的汽車離開裝配線i的離開時間為x[i] 。
?
f[i][j]:表示底盤從起點到裝配站S[i][j]的最快可能時間。
t[i][j]:表示底盤從裝配站S[i][j]移到另一條裝配線花費的時間。
a[i][j]:表示底盤在裝配站S[i][j]停留的時間。
e[i]:表示底盤進入裝配線i的時間。
x[i]:表示底盤完成安裝離開裝配線花費的時間。
?
3?????????問題分析
步驟1:通過工廠最快線路的結構
通過裝配站S[1][j]的最快線路只能是以下二者之一:
(1) 通過裝配站S[1][j-1]的最快線路,然后直接通過裝配站S[1][j]。
(2) 通過裝配站S[2][j-1]的最快線路,從裝配線2移動到裝配線1,然后通過裝配站S[1][j]。
當然,通過裝配站S[2][j]的最快線路也只能是以下二者之一:
(1) 通過裝配站S[2][j-1]的最快線路,然后直接通過裝配站S[2][j]。
(2) 通過裝配站S[1][j-1]的最快線路,從裝配線1移動到裝配線2,然后通過裝配站S[1][j]。
為了解決裝配線調度問題,即尋找通過任意一條裝配線上的第j個裝配站的最快路線,就可以解決裝配線調度問題。
?
步驟2:一個遞歸的解
假設已經完成了汽車的裝配,那么這些路線的較快者即是:
fast =min{f[1][n] + x[1], f[2][n] + x[2]};
初值為:
f[1][1] =e[1] + a[1][1];
f[2][1] =e[2] + a[2][1];
考慮f[i][j](j>1)的計算,很明顯:
f[1][j] =min{f[1][j-2] + a[1][j], f[2][j-1] + t[2][j-1] + a[2][j]};
f[2][j] =min{f[2][j-2] + a[2][j], f[1][j-1] + t[1][j-1] + a[1][j]};
?
步驟3:計算最快時間
整個過程花費時間為O(n);
?
步驟4:構造通過工廠的最快路線
為了構造通過工廠的最快路線,需要構造一個新的數組l[i][j],其值為(1或者2),表示裝配線編號,裝配站j-1被通過S[i][j]的最快路線所使用。
?
4?????????實例與編碼
1. 實例
e[1]=2, e[2]=4;
x[1]=3; x[2]=2;
a[i][j]的值如下表:
| j | 1 | 2 | 3 | 4 | 5 | 6 |
| a[1][j] | 7 | 9 | 3 | 4 | 8 | 4 |
| a[2][j] | 8 | 5 | 6 | 4 | 5 | 7 |
t[i][j]的值如下表:
| j | 1 | 2 | 3 | 4 | 5 |
| t[1][j] | 2 | 3 | 1 | 3 | 4 |
| t[2][j] | 2 | 1 | 2 | 2 | 1 |
?
2. 編碼實現
針對具體問題的實現代碼
?
/*** fastway - 求解裝配線最快線路的時間* Param.:* @a[][]: 在裝配線i上第j個裝配站停留的時間(i=0,1;j=0...(n-1))* @t[][]: 從裝配線i上第j-1個裝配站移動到另一個裝配線的時間* @e[]: 進入裝配線i的時間* @x[]: 在裝配線i上最后一個裝配站離開的時間* @n: 裝配站的個數* @f[][]: 經過裝配線i上第j個裝配站時的最快時間(被賦值)* @flag[][]: 通過裝配站j的最快線路的裝配站j-1所在的裝配線(被賦值)* @fast: 最快線路的時間(被賦值)* @falg: 最快線路的最后一個裝配站所在的裝配線(被賦值)* return:* 無*/ void fastway(int a[][6], int t[][5], int e[], int x[], int n,int f[][6], int flag[][6], int *fastp, int *lastflagp) {int j, fast, lastflag;f[0][0] = e[0] + a[0][0];f[1][0] = e[1] + a[1][0];for (j = 1; j < n; j++){/* 計算f[0][j]和flag[0][j] */if ((f[0][j - 1] + a[0][j]) <= (f[1][j - 1] + t[1][j - 1] + a[0][j])){f[0][j] = f[0][j - 1] + a[0][j];flag[0][j] = 0;}else{f[0][j] = f[1][j - 1] + t[1][j - 1] + a[0][j];flag[0][j] = 1;}/* 計算f[1][j]和flag[1][j] */if ((f[1][j - 1] + a[1][j]) <= (f[0][j - 1] + t[0][j - 1] + a[1][j])){f[1][j] = f[1][j - 1] + a[1][j];flag[1][j] = 1;}else{f[1][j] = f[0][j - 1] + t[0][j - 1] + a[1][j];flag[1][j] = 0;}}/* 計算最優解fast和flag(表示從哪個裝配線上的n裝配站完成) */if ((f[0][n - 1] + x[0]) <= (f[1][n - 1] + x[1])){fast = f[0][n - 1] + x[0];lastflag = 0;}else{fast = f[1][n - 1] + x[1];lastflag = 1;}*fastp = fast;*lastflagp = lastflag; } /*** printway - 求解裝配線最快線路的時間* Param.:* @flag[][]: 通過裝配站j的最快線路的裝配站j-1所在的裝配線(被賦值)* @falg: 最快線路的最后一個裝配站所在的裝配線(被賦值)* @n: 裝配站的個數* return:* 無*/ void printway(int flag[][6], int *lastflagp, int n) {int i, j;i = *lastflagp;printf("line:%d, station:%d\n", i, n);for (j = n; j >= 1; j--){i = flag[i][j];printf("line:%d, stations:%d\n", i, (j - 1));} }?
轉載于:https://www.cnblogs.com/youngerchina/archive/2012/03/17/5624623.html
總結
以上是生活随笔為你收集整理的动态规划 - 装配线调度问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android webview加载网页,
- 下一篇: 虚拟函数的静态决议 和 RTTI 小例子