动态规划的本质是递推问题

动态规划的本质是递推问题

范吉民

课本定义

动态规划即动态地解决问题,从已经解决过的小问题中得到大问题的解,最终得到目标问题的解。动态规划解决的问题具有两个基本特征:

  1. 重叠子问题
  2. 最优子结构

重叠子问题

所谓的重叠,即重复,子问题存在大量重复。这有两个关键点:

  1. 原问题可以分解成为一系列的子问题。
  2. 这些子问题存在者大量的重复。

最优子结构

最终问题的最优解可以从子问题的最优解中获得。

动态规划问题本质上是递推问题

动态规划形式上定义可能看起来复杂或者高级,但其本质就是根据数列递推公式求值的问题,如果能够根据递推公式进一步求出通项公式,那么就能够得到一个O(1)的算法。所以,只要是动态规划问题就一定是递推问题。

实际上面临的问题,能写出递推公式就比较困难了,对于通项公式,通常很难求得,甚至是不可能的。计算机是适合做递推的,但是如果发生指数爆炸或者运算复杂度的幂次很高,那么随着问题规模的增大,计算机也会变得很吃力。

递推问题的三种解法

  1. (反向递推)递归法。按照递推公式直接递归地求解。
  2. (反向递推)备忘法。如果递归中存在潜在的重复计算,那么将每次计算的结果存起来,以后需要时不再求解,直接使用。
  3. (正向递推)制表法。重复计算的根本原因是从上向下求解,大问题可能依赖了很多前项问题,而对这些前项问题的求解,可能存在重复的依赖。
/*===========================
 * f(n) = 2*f(n-1) + 3*f(n-2), f(0)=1, f(1)=2
 *===========================*/
#define N 100

/** 递归(反向递推)法 **/
int f1(int n)
{
	if(n == 0)return 1;
	if(n == 1)return 2;
	return 2*f1(n-1) + 3*f1(n-2);
}

/** 反向递推备忘录法 **/
int memo[10];
int f2(int n)
{
	if(n == 0)return 1;
	if(n == 1)return 2;
	if(memo[n-1]==0) memo[n-1] = f2(n-1);
	if(memo[n-2]==0) memo[n-2] = f2(n-2);
	return 2*memo[n-1] + 3*memo[n-1];
}

/** 正向递推法 **/
int f3(int n)
{
   int fn2 = 1, fn1 = 2;
   for(int i=2;i<=10;i++)
   {
   		int f = 2*fn1 + 3*fn2;
   		fn2 = fn1;fn1 = f;
   }
   return fn1;
}

int main()
{
   printf("f1(%d)=%d\n,N,f1(N));
   printf("f2(%d)=%d\n,N,f2(N));
   printf("f3(%d)=%d\n,N,f2(N));
   return 0;
}

递推问题的数学模型

g n = f ( g 0 , g 1 , g 2 , … , g n − 1 ) , f 是不确定的。 g_n = f( g_0,g_1,g_2,…,g_{n-1} ),f是不确定的。 gn=f(g0,g1,g2,,gn1)f是不确定的。
对于简单问题, f f f可以很简单,可以是线性的,也可以是非线性的,总之,从数学的函数映射理解就能包含所有的情况。

动态规划问题的解题方法

既然动态规划问题是递推问题,那么递推问题的解题方法就是动态规划问题的解题方法。实际上,只不过动态规划问题相对于一般的递推问题,存在一些特殊性:

  1. f f f通常与 m a x , m i n , m a x m i n , m i n m a x , m a x m a x , m i n m i n max, min, max min, min max, max max, min min max,min,maxmin,minmax,maxmax,minmin等待最值函数相关;
  2. 通项可能涉及多项前项,因此存在大量重复依赖。

动态规划是算法中比较难的一类,但是要相信,只要掌握了递推,就能够掌握动态规划。动态规划本身并不是一种独立的解题方法,而是一种问题模式,动态规划的最终解题方法必定可以通过递推问题的三种方法解决。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值