动态规划(一)

什么是动态规划?

     和分治法一样,动态规划(dynamic programming)是通过组合子问题而解决整个问题的解。

     分治法是将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解。

     动态规划适用于子问题不是独立的情况,也就是各子问题包含公共的子子问题。

     此时,分治法会做许多不必要的工作,即重复地求解公共的子问题。动态规划算法对每个子问题只求解一次,将其结果保存起来,从而避免每次遇到各个子问题时重新计算答案。

适用范围

     最优性原理体现为问题的最优子结构特性。当一个问题的最优解中包含了子问题的最优解时,则称该问题具有最优子结构特性。

     最优性原理是动态规划的基础。任何一个问题,如果失去了这个最优性原理的支持,就不可能用动态规划设计求解。

     1.问题中的状态满足最优性原理。

     2.问题中的状态必须满足无后效性。

     所谓无后效性是指:“下一时刻的状态只与当前状态有关,而和当前状态之前的状态无关,当前状态是对以往决策的总结”。

动态规划算法的设计

     两种方法:

     自顶向下(又称记忆化搜索、备忘录):基本上对应着递归函数实现,从大范围开始计算,要注意不断保存中间结果,避免重复计算

     自底向上(递推):从小范围递推计算到大范围

动态规划的重点

    递归方程+边界条件

实例:

爬楼梯问题

     一个人每次只能走一层楼梯或者两层楼梯,问走到第80层楼梯一共有多少种方法。

     设DP[i]为走到第i层一共有多少种方法,那么DP[80]即为所求。很显然DP[1]=1, DP[2]=2(走到第一层只有一种方法:就是走一层楼梯;走到第二层有两种方法:走两次一层楼梯或者走一次两层楼梯)。同理,走到第i层楼梯,可以从i-1层走一层,或者从i-2走两层。很容易得到:

      递推公式:DP[i]=DP[i-1]+DP[i-2]

      边界条件:DP[1]=1   DP[2]=2

备忘录法实现

package dp;

import java.util.Arrays;

public class ClimbStairs {

	public static void main(String[] args) {

		long[] memorandum = new long[81];

		Arrays.fill(memorandum, 0);
		
		memorandum[1] = 1;
		
		memorandum[2] = 2;

		System.out.println(climb(memorandum, 4));

	}

	public static long climb(long[] memorandum, int n) {

		if (memorandum[n] != 0) {

			return memorandum[n];

		}

		if (n == 1) {

			return 1;

		}

		if (n == 2) {

			return 2;

		}

		memorandum[n] = climb(memorandum, n - 1) + climb(memorandum, n - 2);

		return memorandum[n];

	}

}

自底向上法

int i;  
long long dp[81]; /* 注意当n超过75时,结果值将超过int范围 */  
dp[1] = 1;  
dp[2] = 2;  
for(i=3; i <= 80; i++)  
    dp[i] = dp[i-1] + dp[i-2];

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值