Loading [MathJax]/jax/output/CommonHTML/jax.js

Algorithm assignment 1

一、用动态规划方法手工求解下面的问题:

某工厂调查了解市场情况,估计在今后四个月内,市场对其产品的需求量如下表所示。

时期(月) 需要量(产品单位)
1 2
2 3
3 2
4 4

已知:对每个月来讲,生产一批产品的固定成本费为3 (千元),若不生产,则为零。每生产单位产品的成本费为1 (千元)。同时,在任何一个月内,生产能力所允许的最大生产批量为不超过6 个单位。又知每单位产品的库存费用为每月0.5 (千元),同时要求在第一个月开始之初, 及在第四个月末,均无产品库存。

问:在满足上述条件下,该厂应如何安排各个时期的生产与库存,使所花的总成本费用最低?

要求:写出各种变量、状态转移方程、递推关系式、和详细计算步骤。


该题既可以顺推也可以逆推,但逆推的手工计算量较小。因此这里用逆推的方式求解。

  • 变量描述:设n 为总月份,wi 代表第i个月的需求量,ui 代表第i个月的产量,生产固定成本c1=3 ,生产单位产品成本费c2=1 ,单位产品的库存费c3=0.5 ,单月最大生产量maxp=6

  • 状态转移方程

    si为第i个月的库存,则si+1=si+uiwi,且si00uimaxp

    vi为第i个月的花费,则vi=c3si+{c2ui+c1,ui>00,ui=0

    fi(si)为第i个月后,库存为si的最小成本,则

    fi(si)=minui{vi+fi+1(si+1)}

    最终所求为f1(0)

  • 递推关系式

    {fn(0)=0fi(si)=minui{vi+fi+1(si+1)}

  • 计算步骤

    由题知,所求n=4;w={2,3,2,4},所以有u4=s5s4+w4=4s4,即0s44

    f4(s4)=minu4{v4+f5(0)}=minu4{0.5s4+{1u4+3,u4>00,u4=0}{f4(0)=7,u4=4f4(1)=6.5,u4=3f4(2)=6,u4=2f4(3)=5.5,u4=1f4(4)=2,u4=0

    所以有u3=s4s3+w3,即0s36

    f3(s3)=minu3{v3+f4(s4)}=minu3{0.5s3+{1u3+3,u3>00,u3=0}{f3(0)=11,u3=6f3(1)=10.5,u3=6f3(2)=8,u3=0f3(3)=8,u3=0f3(4)=8,u3=0f3(5)=8,u3=0f3(6)=5,u3=0

    所以有u2=s3s2+w2,即0s29

    f2(s2)=minu2{v2+f3(s3)}=minu2{0.5s2+{1u2+3,u2>00,u2=0}{f2(0)=16,u2=5f2(1)=15.5,u2=4f2(2)=15,u2=3f2(3)=12.5,u2=0f2(4)=12.5,u2=0f2(5)=10.5,u2=0f2(6)=11,u2=0f2(7)=11.5,u2=0f2(8)=12,u2=0f2(9)=9.5,u2=0

    s1=0u1=s2s1+w1

    f1(s1)=minu1{v1+f2(s2)}=minu1{0.5s1+{1u1+3,u1>00,u1=0}f1(0)=20.5,u1=5

    u=[5,0,6,0]s=[0,3,0,4],即4个月分别生产5、0、6、0单位产品,各月库存量分别为0、3、0、4,总成本最低为f1(0)=20.5

二、用动态规划方法编程求解下面的问题:

某推销员要从城市v1 出发,访问其它城市v2v3v6 各一次且仅一次,最后返回v1。D为各城市间的距离矩阵。

D=v1v2v3v4v5v6[010203040501201830252123190510153432408164527111001856221620120]

问:该推销员应如何选择路线,才能使总的行程最短?

要求:写出递推关系式、伪代码和程序相关说明,并分析时间复杂性。 (请遵守第一节课提出的有关 assignment 的要求)


  • 变量描述:记城市数量n=6,城市编号为0,1,2,,n1,距离矩阵为D

  • 状态转移方程:设fi,S代表推销员走到第i个城市,已经访问过的城市集合为S,则

    fi,S=min{fj,S{i}+Dj,i}

  • 递推关系式:初始时S为空,fi,S=0

    {fi,S=0fi,S=min{fj,S{i}+Dj,i}

  • 伪代码

    func TSP(n, D){
    	// Input: n城市数量,D为距离矩阵下标从0开始
    	// Output: 一个数,代表从v1=0出发,最后回到v1的最小距离
    	初始化f为INF
    	将v1添加进集合S,此时f[i][S]=0
    	从{v1}开始枚举集合S的状态
    		枚举第i个城市是否在集合内,如果在
    			枚举不在集合内的第j个城市
    				将j加入集合S记为S‘,此时花费为f[i][S] + D[i][j]f[j][S']=min{f[j][S'], f[i][S] + D[i][j]}
    	则得到f[i][S]为从0出发,最后集合状态为S的最小
    	最后加上从最后经过的城市返回v1的距离,输出答案
    }
    
  • 时间复杂度O(n22n)

  • 附程序代码

    #include<iostream>
    #include<cstring>
    using namespace std;
    #define INF 0x3f3f3f3f
    const int n = 6;
    const int D[6][6]={
        {0,10,20,30,40,50},
        {12,0,18,30,25,21},
        {23,19,0,5,10,15},
        {34,32,4,0,8,16},
        {45,27,11,10,0,18},
        {56,22,16,20,12,0}
    };
    int f[10][1024];
    int main() 
    {
        memset(f, INF, sizeof(f));
        f[0][1] = 0;
        int tot = (1 << n) - 1;
        for (int s = 1; s <= tot; s++) {
            for (int i = 0; i < n; i++) {
                if ((s >> i & 1 == 0) || (f[i][s] == INF)) continue;
                for (int j = 0; j < n; j++) if ((s >> j & 1) == 0)
                    f[j][s | 1 << j] = min(f[j][s | 1 << j], f[i][s] + D[i][j]);
            }
        }
        int ans = INF;
        for (int i = 0; i < n; i++) if (f[i][tot] < INF)
            ans = min(ans, f[i][tot] + D[i][0]);
        cout << ans << endl; 
    }
    
posted @   ProboxDu  阅读(736)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示