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数组。

祝馒头天天开心!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值