概念
动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果
参考点【重要】
- 子路径最优解也是全局最优解,如果不满足则不适合使用动态规划;
- 将问题拆分为多个子问题,每个子问题解法相同(如果有不同可以利用分段函数分析);
- 维护一个数组(可以是多维数组)
- 拓展:无后效性
案例
题目:求数组中任意子数组的最大和,如[1,-3,6,2,-1],子数组累加和的最大值为8。
分析:可以暴力计算,但是时间复杂度为O(n²),使用动态规划思路:
[1]
{
[1]
}=> add_max=1
[1,-3]
{
[1,-3]
[-3]
}=> add_max=-2
[1,-3,6]
{
[1,-3,6]
[-3,6]
[6]
↓
//上一次的最大值与最后一位累加
[-2, 6]
[6]
}=> add_max=6
[1,-3,6,2]
{
[1,-3,6,2]
[-3,6,2]
[6,2]
[2]
↓
//上一次的最大值与最后一位累加
[6, 2]
[2]
}=> add_max=8
[1,-3,6,2,-1]
{
[1,-3,6,2,-1]
[-3,6,2,-1]
[6,2,-1]
[2,-1]
[-1]
↓
//上一次的最大值与最后一位累加
[8, -1]
[-1]
}=> add_max=7
最后在[1, -2, 6, 8, 7]中的最大值8。
*时间复杂度O(n)
//伪代码
//最大累加和
public int GetMaxSubarrAdd(int[] arr)
{
if(arr.Length <= 0)
throw;
//每个位置前边的子集合最大累加和的集合记录
int[] target = new int[arr.Length];
target[0] = arr[0];
for(int i = 1; i < arr.Length; i++)
{
//前边的最大累加和 + 最后一位,与最后一位对比,取最大值,放到维护的列表中
target[i] = Math.Max(target[i - 1] + arr[i], arr[i]);
}
retrun target.MaxItem();
}