A Simple Example of Dynamic Programming using perl scripts

【備註】:借鑑《Introduction of Algorithm》seconde edition第十五章的內容,可以在書上找到原實例。

1、概念和意義:
動態規劃(dynamic programming)是通過組合子問題的解而解決整個問題的。programming是指一種規劃,而不是指寫計算機代碼。
分治算法是指將問題劃分爲一些獨立的子問題,遞歸地求解各子問題,然後合併子問題的解而得到原問題的解。動態規劃適用於子問題不是獨立的情況,也就是各子問題包括公共的子子問題。在這種情況下,若用分治法則會做許多不必要的工作,即重複地求解公共的子子問題。動態規劃算法對每個子子問題只求解一次,將其結果保存在一張表中,從而避免每次遇到各個子問題重新計算答案。
動態規劃通常應用於最優化問題。此類問題可能有很多種可行解。每個解有一個值,而我們希望找出一個具有最優(最大或最小)值的解。稱這樣的解爲該問題的一個最優解(而不是確定的最優解)。
動態規劃算法的設計可以分爲如下4個步驟:
(a)描述最優解的結構。
(b)遞歸定義最優解的值。
(c)按自底向上的方式計算最優解的值。
(d)由計算出的結果構造一個最優解。
 
2、一個簡單例子,裝配線調度,只有兩條可選路徑。
(1)問題描述:
汽車公司又兩條裝配線:assembly line1, assembly line2.
一條裝配線有六個裝配站,station1, ... , station6
進入(chassis enter)和離開(complete exit) assembly line 的時間不一致.
產品必須依次經過裝配站,同一條assembly line1上station轉換不計時間,但是不同的assemblyline轉換是要消耗時間。
具體標記如下:

一個簡單實例:

僞代碼:

perl代碼簡單執行,僅僅是簡單執行,不具有一般性。

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my @stations = ([2,7,9,3,4,8,4,3], [4,8,5,6,4,5,7,2] ); # 0,1,2,3,4,5,6,7
my @transfer = ([2,3,1,3,4], [2,1,2,2,1] ); # 0,1,2,3,4,5

my (@fastway, @line);

($fastway[0][0], $fastway[0][1]) = ($stations[0][0], $stations[0][0]+$stations[0][1] );
($fastway[1][0], $fastway[1][1]) = ($stations[1][0], $stations[1][0]+$stations[1][1] );
($line[0][0], $line[0][1]) = (0,0);
($line[1][0], $line[1][1]) = (1,1);

for( my $i=2; $i<=6; $i++ ){

        # for line one
        if( $fastway[0][$i-1] <= $fastway[1][$i-1] + $transfer[1][$i-2] ){
                $fastway[0][$i] = $fastway[0][$i-1] + $stations[0][$i];
                $line[0][$i] = 0;
        }else{
                $fastway[0][$i] = $fastway[1][$i-1] + $transfer[1][$i-2] + $stations[0][$i];
                $line[0][$i] = 1;
        }

        # for line two
        if( $fastway[1][$i-1] <= $fastway[0][$i-1] + $transfer[0][$i-2] ){
                $fastway[1][$i] = $fastway[1][$i-1] + $stations[1][$i];
                $line[1][$i] = 1;
        }else{
                $fastway[1][$i] = $fastway[0][$i-1] + $transfer[0][$i-2] + $stations[1][$i];
                $line[1][$i] = 0;
        }

}

$fastway[0][7] = $fastway[0][6] + $stations[0][7];
$fastway[1][7] = $fastway[1][6] + $stations[1][7];

my $line = 0;
$line[$line][7] = $line;
$line[$line][7] = $line = 1 if( $fastway[0][7] >= $fastway[1][7] );

print "StepMarker\tStations\tTimeCost\n";
for( my $i=0; $i<8; $i++ ){

        my $index;
        if( $i==0 ) {
                $index = "EnterTimeCost";
        }elsif( $i==7 ) {
                $index = "TotalTimecost";
        }else{
                $index = "FinishStation";
        }

        print join("\t", "$index$i", $line[$line][$i]+1, $fastway[$line][$i], "\n" );

}

python代碼:
stations = [[2,7,9,3,4,8,4,3], [4,8,5,6,4,5,7,2]]
transfer = [[2,3,1,3,4], [2,1,2,2,1]]

fastway = [ [stations[0][0], stations[0][0]+stations[0][1]], [stations[1][0], stations[1][0]+stations[1][1]] ]
line = [ [0,0], [1,1] ]

for i in range(2,7):

        # for line one
        if fastway[0][i-1] <= (fastway[1][i-1] + transfer[1][i-2]):
                fastway[0].append( fastway[0][i-1] + stations[0][i] )
                line[0].append( 0 )
        else:
                fastway[0].append( fastway[1][i-1] + transfer[1][i-2] + stations[0][i] )
                line[0].append( 1 )

        #for line two
        if fastway[1][i-1] <= (fastway[0][i-1] + transfer[0][i-2]):
                fastway[1].append( fastway[1][i-1] + stations[1][i] )
                line[1].append( 1 )
        else:
                fastway[1].append( fastway[0][i-1] + transfer[0][i-2] + stations[1][i] )
                line[1].append( 0 )

fastway[0].append( fastway[0][6] + stations[0][7] )
fastway[1].append( fastway[1][6] + stations[1][7] )

li = 0
line[li].append( 0 )
if fastway[0][7] >= fastway[1][7]:
        li = 1
        line[li].append( 1 )

print "StepMarker\tStations\tTimeCost"
for i in range(8):

        if i==0: index = "EnterTimeCost"
        elif i==7: index = "TotalTimecost"
        else: index = "FinishStation"
        print '%s%d\t%d\t%d' % (index, i, line[li][i]+1, fastway[li][i])



難點有兩個:一個是遞推公式的歸納,二是進程的表示,比如line數組。

祝饅頭天天開心!!

發佈了59 篇原創文章 · 獲贊 31 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章