5算法设计与分析笔记(Authored by M.H Alsuwaiyel, Saudi)

第五章 动态规划

  • 动态规划算法与分治法类似,其基本思想也是将求解问题分解为若干个子问题。与分治法不同的是,动态规划问题中子问题不是独立的,可能重复计算,所以动态规划旨在优化问题减少重复子问题的计算。
  • 简言之,动态规划的实质是分治消除冗余

矩阵链相乘

  • 假设我们要计算三个矩阵的乘积即M_1M_2M_3,这3个矩阵的维数分别为2\times 10,10\times 2,2\times 10,我们可以有((M_1M2)M_3),(M_1(M_2M_3))两种方式。前者需要2\times 2\times 10=80次乘法,后者需要10\times 2\times 10+2\times 10\times 10=400次乘法。可见对于n个矩阵M_1,M_2...M_n链乘的耗费,取决于n-1个乘法的执行顺序。下面我们讨论找出n个矩阵链相乘的最小数乘次数。

Catalan数

  • f(n)是求n个矩阵相乘的所有放置括弧的方法数。对于(M_1M_2···M_k)\times (M_{k+1}M_{k+2}···M_{n}),对于前k个矩阵有f(k)种放置方法,对于余下的有f(n-k)种放置方法,总共有f(k)f(n-k)种放置方法,则对于n个矩阵的所有放置方法数:

    f(n)=\sum_{k=1}^{n-1}f(k)f(n-k),显然f(2)=1,f(3)=2(两个矩阵只有一种乘法,三个矩阵有两种乘法),我们假定f(1)=1,可以证明:f(n)={1\over n}{\binom{2n-2}{n-1}}

  • 上述递推式产生了Catalan数,定义C_n=f(n+1),它的前11项为:1,1,2,5,14,42,132,429,1430,4862,16~796。因此矩阵个数n逐渐变大时,采用简单的暴力算法是十分低效的。

最小矩阵链乘数MATCHCHAIN

  • 对于每个i,1\leq i<n,矩阵M_i的列数一定等于矩阵M_{i+1}的行数。因此我们指定n+1维数r_1,r_2,···,r_n,r_{n+1},其中r_i,r_i+1分别表示矩阵M_i的行数和列数(最右边的矩阵的列数与前面无关,所以会有r_{n+1})。并且,我们用M_{i,j}表示M_iM_{i+1}···M_j的乘积,M_{i,j}的数量乘法耗费记为C[i,j]

  • k\in (i,j),那么有M_{i,j}=M_{i,k-1}M_{k,j}。显然这样按k划分后,C[i,j]=C[i,k-1]+C[k,j]+M_{i,k-1}M_{k,j}M_{i,k-1}M_{k,j}实际上也是两个维数分别为r_i\times {r_k}、r_k\times r_{j+1}的新矩阵相乘)。

  • 于是我们得到C[i,j]=min\{C[i,k-1]+C[k,j]+r_ir_kr_{j+1}\},对于求M_1M_2···M_n,则我们需要解决递推式C[1,n]=min\{C[1,k-1]+C[k,n]+r_1r_kr_{n+1}\}

  • 为避免重复计算,考虑到C[i,j]=C[j,i],我们将计算二维数组C的右上半部分(对角线向上计算),最终C[1,n]下图中的C[1,6]即为所求。

    • 例:给出5个矩阵如下:(d_0表示第一条对角线)

      M_1:5\times10,M_2:10\times4,M_3:4\times6,M_4:6\times10,M_5:10\times2

      易知,d_0上的元素均为0

      C[1,2]

      • k=2,C[1,2]=0+0+5*10*4=200

      C[2,3]

      • k=3,C[2,3]=0+0+10*4*6=240

      ······

      C[1,3]

      • k=2,C[1,3]=200+240+5*10*6=740
      • k=3,C[1,3]=200+0+5*4*6=320
      • C[1,3]=min\{740,320\}=320

      ······依次计算d_1、d_2、···、d_{n-1}得到如下表格:

      0 1 2 3 4
      C[1,1]=0 C[1,2]=200 C[1,3]=320 C[1,4]=620 C[1,5]=348
      C[2,2]=0 C[2,3]=240 C[2,4]=640 C[2,5]=248
      C[3,3]=0 C[3,4]=240 C[3,5]=168
      C[4,4]=0 C[4,5]=120
      C[5,5]=0

MATCHCHAIN

输入:n个矩阵的链的维数对应于正整数数组r[1···n+1]。

输出:n个矩阵相乘的数量乘法最小次数。

for i <- 1 to n
    C[i,i] <- 0 #对角线0的元素填充0
end for
for d <- 1 to n-1 #遍历n条对角线
    for i <- 1 to n-d #遍历第d条对角线的所有元素
        j <- i+d
        C[i,j] <- infty
        for k <- i+1 to j #尝试所有可能的k值求min
            C[i,j] <- min{C[i,j], C[i,k-1]+C[k,j]+r[i]r[k]r[j+1]}
        end for
    end for
end for
return C[1,n]
  • 观察MATCHCHAIN算法易知,三层for循环嵌套,时间复杂度为\Theta(n^3),算法的空间复杂度取决于所需要的r数组,即\Theta(n^2)

0/1背包问题

  • 背包问题的定义如下:设U=\{ u_1,u_2,···,u_n\}n项物品的集合,现要将他们放入一个容量为C的背包中,对于第i个物品,s_i,v_i分别表示其体积和价值。

    数学化描述:给出有n项元素的集合U,找出一个子集合S\subseteq U,使得\sum_{u_i\in S}v_i在约束条件\sum_{u_i\in S}s_i \leq C下最大。

  • 之所以被称为0/1背包问题,是因为对于集合U的每个物品,要么被选中,要么不被选中。

  • 为了装满背包我们给出以下递推式,设V[i,j]表示从前i项中取出物品放入体积为j的背包的最大价值(V~means~Value)。显然,V[0,j]=0因为对于所有体积为j的背包,从0个物品中取得的最大价值为0V[i,0]=0因为对于体积为0的背包,前i项物品无法放入该背包。

    V[i,j]= \begin{cases}0,~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~i=0~or~j=0\\ V[i-1,j],~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~j<s_i\\ max\{V[i-1,j],V[i-1,j-s_i]+v_i\},~~~~~~~~i>0~and~j\geq s_i \end{cases}

    • V[i-1,j]:当j<s_i时,不能再容纳更多的物品,所以V[i,j]就为i-1的价值;
    • V[i-1,j-s_i]+v_i:当j\geq s_i时,可以容纳第i个物品,j要腾出s_i的体积去容纳第i个物品
  • 例:有容量为10的背包,要装入5种体积为2,3,4,4,6的物品,它们的价值分别是4,5,4,7,5,即物品a\{3,5\},b\{2,4\},c\{4,4\},d\{4,7\},e\{6,5\}

    • 对于i=0~orj=0的行和列全部填0

    • i=1,放入a物品,由于s_a=3,所以从j\geq3开始考虑,填入其价值v_a=5

    • i=2,放入b物品,由于s_b=2,所以从j\geq2开始考虑,j=2得到更新V[2-1,2-2]+v_2=4j\geq5,均可得到更新V[2-1,j-2]+v_2=5+4=9

    • i=3,放入c物品,从j\geq4开始考虑,显然把ab(5)取出放入c(4)的价值是缩小的······;直到j\geq9a,b,c可以同时放入价值最大为13

    • i=4,放入d物品,从j\geq4开始考虑,ab(5)<d(7)所以更新V[4,4];对于V[4,6](a,b),取出a放入d的价值更大,V[4,6]=4+7=11>9······

      ······

    • 最终依据表格,选择a,b,d价值最大为16

背包KNAPSACK算法

KNAPSACK

输入:物品集合U={u1, u2,..., un},体积分别为s1, s2,..., sn,价值分别为v1, v2,..., vn,容量为C的背包。

输出:\sum_{u_i\in S}v_i在约束条件\sum_{u_i\in S}s_i \leq C下最大,S\subseteq U

for i <- 0 to n
    V[i,0] <- 0 
end for
for j <- 0 to C
    V[0,j] <- 0
end for
for i <- 1 to n
    for j <- 1 to C
        V[i,j] <- V[i-1,j]
        if si <= j then V[i,j] <- max{V[i,j], V[i-1,j-si]+vi}
    end for
end for
return V[n,C]
  • 由于计算表格中的每一项需要\Theta(1)的时间,所以KNAPSACK算法的时间复杂度为\Theta(nC),空间复杂度为\Theta(C)

所有点对的最短路径问题

  • G=(V,E)是一个有向图,问题描述为:找出每个顶点到其他所有顶点的距离,这里xy的距离是指从xy的最短路径长度。
  • 为方便研究,设n个顶点在集合V=\{1,~2,~...,~n\}中,顶点i,j的距离为D[i,j]。初始时,D[i,j]就是有向图的边长l[i,j],若i,j不直接连通则D[i,j]=\infty

Floyd算法

  • 对于任意两个顶点i,j,它们可以通过其他顶点间接连通,所以我们可以通过比较i,j直接连通的长度与i,j通过顶点k间接连通的长度,选取较小值。当然,顶点i,j间接连通不一定只经过一个顶点k,这是一个递归过程。

  • 开始时,如果i\neq j并且(i,j)G中的边,则置D_0[i,i]=0,D_0[i,j]=l[i,j],否则置D_0[i,j]=\infty。然后顺序迭代n次,D_k[i,j]表示从顶点ij的距离,且经过的中间顶点编号不大于k,则:

    D_k[i,j]=min\{ D_{k-1}[i,j], D_{k-1}[i,k]+D_{k-1}[k,j] \}

FLOYD

输入:以矩阵l表示的有向图G。

输出:矩阵D,使得D[i,j]表示顶点i到顶点j的距离。

D <- l #将l复制到矩阵D
for k <-  1 to n
    for i <- 1 to n
        for j <- 1 to n
            D[i,j]=min{D[i,j], D[i,k]+D[k,j]} #看是原距离更小,还是加入顶点k后更小
        end for
    end for
end for
return D
  • 例如,考虑如下有向图,求矩阵D

    • D_0即为有向图GD_0中的D[3,3]=0,图片错误);

    • k=1,以1为媒介重新计算距离,对于D[2,3],若借助顶点1距离为8+9=17>6所以不变;对于D[3,2],借助顶点1距离为1+2=3< \infty得到更新;

      ······

  • FLOYD算法是三重循环嵌套,时间复杂度为\Theta(n^3)。需要二维数组D空间复杂度为\Theta(n^2)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容