introduction
大部分书籍介绍“动态规划”时,都会从“菲波纳切数列”讲起。
菲波纳切数列
递归解法
C++ 代码如下
unsigned long int fib(const int n) {
switch (n)
{
case 0:
return 0;
case 1:
return 1;
default:
return fib(n - 1) + fib(n - 2);
}
}
DP
解决 DP 问题的关键因素之一,是要找出问题递归方程,然后就好解了。
菲波纳切数列的递归定义如下:
纯 DP
自底向上,使用数组存储过程值。
unsigned long int fib(const int n) {
vector<unsigned long int> sum;
sum.push_back(0);
sum.push_back(1);
for (int i = 2; i <= n; i++) {
sum.push_back(sum[i - 1] + sum[i - 2]);
}
return sum[n];
}
优化 DP
自底向上,但是没有使用数组存储过程值——不记录全局解(过程值)的 DP 算法,其本质就类似于贪心算法了。
unsigned long int fib(const int n) {
switch (n)
{
case 0:
return 0;
case 1:
return 1;
}
unsigned long int a = 0, b = 1, sum = 0;
for (int i = 2; i <= n; i++) {
sum = a + b;
a = b;
b = sum;
}
return sum;
}
经典 DP 题解
最大连续子数组和问题
递归方程
curr(i) = max(0, curr(i-1)) + arr[i]
如果 curr > result ,则更新 result = curr,否则 result 保持原值
解题代码
int maxSubArray(const vector<int> &v) {
int curr = 0;
int ret = v[0];
for (auto e : v) {
if (curr >= 0) {
curr += e;
}
else {
curr = e;
}
ret = curr > ret ? curr : ret;
}
return ret;
}