1.动态规划:初识
动态规划(英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。
实际上是对暴力递归的一种优化,把已经计算过的信息保存起来,下次要用时不用重复计算,并且通过求解动态数组的方式代替了函数的递归调用。
第一步优化在于对计算结果的存储,避免重复计算。可以优化成下面描述的记忆化搜索方法。
第二步优化在于对递归函数调用的优化,直接从bace case 反推,而不是从上往下调用。
2.例子:
1.1机器人走路问题
机器人在有N个位置的路上走,开始机器人在M位置,机器人可左右移动,到1位置时只能右移,到N位置时只能左移,机器人从起始位置M到目标位置P,共走K步,求移动的方法数
参靠左神代码编写:
#include <iostream>
#include <vector>
using namespace std;
/* 原始暴力递归
* N:总位置数 cur:当前位置 rest:剩余步数 aim:目标位置
* 返回: 从cur到 aim 的方法数
*/
int way1(const int N, int rest, int cur, const int aim)
{
//第一步,返回边界
if (rest == 0) // base case
{
return (cur == aim ? 1 : 0);
}
//第二步,看当前位置的分指数个数(分普通情况和特殊情况)
//特殊情况,来到最左边时
if (cur == 1)
{
return way1(N, rest - 1, 2, aim);
}
//来到最右端时
if (cur == N)
{
return way1(N, rest - 1, N - 1, aim);
}
//来到中间位置时
return way1(N, rest - 1, cur + 1, aim) + way1(N, rest - 1, cur - 1, aim);
}
//傻缓存法改进(记忆化搜素)
int way2(const int N, int rest, int cur, const int aim, vector<vector<int>> &dp) //注意传引用
{
if (dp[cur][rest] != -1)
{
return dp[cur][rest];
}
if (rest == 0) //边界条件 步数走完当前值到达目标点时有一种方法,否则无
{
return cur == aim ? 1 : 0;
}
//如果此条信息计算过,则直接返回dp数组里存的值
int ret = 0; //存返回值,用来给dp数组赋值
if (cur == 1)
{
ret = way2(N, rest - 1, 2, aim, dp);
}
else if (cur == N)
{
ret = way2(N, rest - 1, N - 1, aim, dp);
}
else
{
ret = way2(N, rest - 1, cur - 1, aim, dp) + way2(N