动态规划思想《从入门到放弃》

动态规划的定义

将原问题拆解成若干子问题 ,同时保存子问题的答案,使得每个子问题只求解一次,最终获得原问题的答案。

动态规划的一般流程

在这里插入图片描述

例子1:一维空间的动态规划

题目:求斐波那契数列

  • 暴力递归解决
// 使用递归解决
int fibonacci(int i) {
	return i <= 1 : i : fibonacci(i - 1) + fibonacci(i - 2);
}

暴力递归的时间复杂度是指数级,我们需要使用记忆化搜索去解决这个问题

  • 记忆化搜索(动态规划思想)
// 使用动态规划思想 记忆化搜索
int fibonacci(int fib) {
	// 定义一个数组 存储第N项的斐波那契数
    int[] cache = new int[fib + 1];
    // 遍历
    for (int i = 0; i < cache.length; i++) {
        if (fib <= 1) {
            cache[i] = i;
            continue;
        }
        cache[i] = cache[i - 2] + cache[i - 1];
    }
    return cache[fib];
}

复杂的动态规划

复杂的动态规划:

  1. 维度变化了 有可能是二维或三维空间;
  2. 中间可能会有取舍最优子结构

题目2:不同路径
题目描述:一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
在这里插入图片描述
对于上述问题,由于每次只能 向右或向下 走,于是我们可以转变为子问题:
子问题1:对于A如何走到右下角
子问题2:对于B如何走到右下角
所以总共的走法就等于 【A】的子问题的解+【B】的子问题的解

  • 解法一:使用常规的递归解法
// 使用递归的解法
int paths(int m, int n) {
	// 定义一个二维网格
	int[][] table = new int[m][n];
	// 调用递归函数
	return dfs(table, 0, 0);
}
int dfs(int[][] table, int row, int col) {
	// 递归终止条件
	// 1.1 处理边界值
	if (row < 0 || row >= table.length || col < 0 || col >= table[0].length) {
		return 0;
	}
	// 1.2 若走到目的地 则返回1
	if (row == table.length - 1 && col == table[0].length - 1) {
		return 1;
	}
	// 转换成子问题的解
	return dfs(table, row + 1, col) + dfs(table, row, col + 1);
}
  • 解法二:记忆化搜索
/**
	使用动态规划思想解决
	可以发现 每一格的路径数量是由其上一格和左边一格的路径总数决定的
*/
int paths(int m, int n) {
	// 定义一个二维矩阵
	int[][] table = new table[m][n];
	// 先初始化第一行和第一列
	for (int i = 0; i < m; i++) {
		table[m][0] = 1;
	}
	for (int i = 0; i < n; i++) {
		table[0][n] = 1;
	}
	for (int i = 1; i < m; i++) {
		for (int j = 1; j < n; j++) {
			table[i][j] = table[i - 1][j] + table[i][j - 1];
		}
	}
	return table[m - 1][n - 1];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rabbit_zli

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值