ADS08 Dynamic Programming

动态规划DP,就是用分治的方法,但是记录下小问题的解,减少重复计算。

Fibonacci Numbers

问题描述

计算:T(N) = T(N-1) + T(N-2)

解法

1.令NextoLast = T(0), Next = T(1)

2.计算T(i) = NextToLast + Next

3.更新Next = NextToLast, NextToLast = T(i)

4.重复N次。

这个算法需要记录的只是最近的两次。

复杂度为O(N)

int  Fibonacci ( int N ) 
{   int  i, Last, NextToLast, Answer; 
    if ( N <= 1 )  return  1; 
    Last = NextToLast = 1;    /* F(0) = F(1) = 1 */
    for ( i = 2; i <= N; i++ ) { 
        Answer = Last + NextToLast;   /* F(i) = F(i-1) + F(i-2) */
        NextToLast = Last; Last = Answer;  /* update F(i-1) and F(i-2) */
    }  /* end-for */
    return  Answer; 
}

矩阵乘法

问题描述

对于矩阵 M 1 ⋅ M 2 ⋅ M 3.... M n M1\cdot M2 \cdot M3....M_n M1M2M3....Mn,求最小计算cost

已知对于矩阵 M ( i , j ) ⋅ M ( j , k ) M(i,j) \cdot M(j,k) M(i,j)M(j,k),cost为 i ⋅ j ⋅ k i \cdot j\cdot k ijk

解法

m i , j = M i M i + 1 ⋅ M j m_{i,j} = M_iM_{i+1}\cdot M_j mi,j=MiMi+1Mj M i M_i Mi r i × r i − 1 r_i\times r_{i-1} ri×ri1的矩阵

m i , j = min ⁡ { m i l + m l + 1 , j + r i − 1 r l r j } , i < j m_{i,j}=\min\{m_{il}+m_{l+1,j}+r_{i-1}r_lr_j\},i< j mi,j=min{mil+ml+1,j+ri1rlrj},i<j
m i . i = 0 m_{i.i}=0 mi.i=0

需要存的表(从下方开始算)是:在这里插入图片描述

void OptMatrix( const long r[ ], int N, TwoDimArray M ) 
{   int  i, j, k, L; 
    long  ThisM; 
    for( i = 1; i <= N; i++ )   M[ i ][ i ] = 0; 
    for( k = 1; k < N; k++ ) /* k = j - i */ 
        for( i = 1; i <= N - k; i++ ) { /* For each position */ 
	j = i + k;    M[ i ][ j ] = Infinity; 
	for( L = i; L < j; L++ ) { 
	    ThisM = M[ i ][ L ] + M[ L + 1 ][ j ] 
		    + r[ i - 1 ] * r[ L ] * r[ j ]; 
	    if ( ThisM < M[ i ][ j ] )  /* Update min */ 
		M[ i ][ j ] = ThisM; 
	}  /* end for-L */
        }  /* end for-Left */
}

复杂度O(N3)

Optimal Binary Search Tree

问题描述

对于一颗BST,每个节点被搜索到的可能性为pi,求怎么改变根,使得达到最短的搜索时间。

注意,点的顺序是固定的。改变的只能是谁去当根。

最短的搜索时间是,该点到根的路径长度乘上该点的可能性,对所有点求和。

解法

i到j的cost,如果挑选l为根

ci,j=ci,l-1+cl+1,j+pi+…pj

简单一点来说i到j的cost,就是i到j里面挑一个点作为根,根到i和根到j的点组成左右子树,cost是左右子树cost和+i到j所有的点的搜索可能性之和

如果i=j,cost=pi

第二部分是一个常数。

在这里插入图片描述
对于上面这张表,存储了i到j范围中cost最小的值。记录下的根在计算下一个cost时没有用处,但是在最后看结果时有用。

比如计算break到do的cost

首先,所有的p加起来,是0.65是个常数,然后是左右子树cost查表,比如让char做根,就是查左树break到case和右子树do的cost

让break做根,左+右=0+0.66,

让case做根,左+右=0.22+0.3

让char做根,左+右=0.58+0.05

让do做根,左+右=1.02+0

最小的是case,0.52+0.65=1.17,填入break到do

算法对于i,j要遍历每一个元素。i*(n-i)*(n-i),一共N^3

复杂度为O(N3)

All-Pairs Shortest Path

问题描述

找到每一对点之间最短距离

解法

Dk[i][j]是长度小于等于k的路径中连接i,j的最短路径长度,DN-1[i][j]就是解。

D k [ i ] [ j ] = min ⁡ { D k − 1 [ i ] [ j ] , D k − 1 [ i ] [ l ] + D k − 1 [ l ] [ j ] } D^k[i][j]=\min\{ D^{k-1}[i][j] , D^{k-1}[i][l] + D^{k-1}[l][j] \} Dk[i][j]=min{Dk1[i][j],Dk1[i][l]+Dk1[l][j]}

算法是:首先在平面上找一个点,计算所有其他两个点i,j通过这个点的最短路径,然后更新i,j的最短路径。

然后更新这个点,注意顺序不能反了,因为这样会导致,计算i到k,j到k的距离不是最短的,更新出来没有意义。

O(N3)

Product Assembly

有两条线路,一辆车可以在站点换线。不同线路两个站点之间的时间不同。求总时间最小。

解法

用f[i][j]记录下到第i个站点,使用j线的时间。

f [ i ] [ 0 ] = min ⁡ { f [ i − 1 ] [ 0 ] + t [ i ] [ 0 ] , f [ i − 1 ] [ 1 ] + c t [ i ] [ 1 ] } f[i][0]=\min\{f[i-1][0]+t[i][0],f[i-1][1]+ct[i][1]\} f[i][0]=min{f[i1][0]+t[i][0],f[i1][1]+ct[i][1]}

f [ i ] [ 1 ] = min ⁡ { f [ i − 1 ] [ 1 ] + t [ i ] [ 1 ] , f [ i − 1 ] [ 0 ] + c t [ i ] [ 0 ] } f[i][1]=\min\{f[i-1][1]+t[i][1],f[i-1][0]+ct[i][0]\} f[i][1]=min{f[i1][1]+t[i][1],f[i1][0]+ct[i][0]}

解是min{f[n][0],f[n][1]}

O(N)空间和时间复杂度

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值