• 动态规划 装配线调度问题



    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/p/5624623.html
Copyright © 2020-2023  润新知