动态规划算法

来源:互联网 发布:大数据 nosql 编辑:程序博客网 时间:2024/06/05 19:52
1 动态规划的思想
动态规划也是采取的分治的思想,关键点就在于怎么去分。
在钢管分割的问题上,可以这样去思考问题,假设钢管长度为N,最优解是将其分割为k段。那么当将钢管分割为2段时,
我们假设x = L(1) + L(2) + ... + L(p), y = L(p+1) + L(p+2) + ... + L(k)。则必然是L(1) + L(2) + ... + L(p)是
长度为x的最优解,L(p+1) + L(p+2) + ... + L(k)是长度为y的最优解。证明方法很简单,采取反证的思想,如果
L(1) + L(2) + ... + L(p)不是长度为x的最优解,那么L(1) + L(2) + ... + L(p) + L(p+1) + L(p+2) + ... + L(k)必然
不是长度为n的最优解。
所以说将n分割为x+y的时候,并且通过一定次数的继续分割,必然会产生诸如L(1) + L(2) + ... + L(p) + L(p+1) + L(p+2) + ... + L(k)
的最优解。也就是说可以通过2分法来产生最优解,但是2分法的两个局部最优解的和就不一定是全局最优解了。


根据以上思想,可以得出钢管最优解的一个递归公式
r(n) = max(pn,(r1 + r(n-1)),(r2 + r(n-2)),...(r(n-1), r1));

2 问题的简化
可以这么想,将钢条分为两段,第一段的长度依次递加,那么所以递归式可以简化为:
r(n) = max(pi + r(n-i)), 1<=i<=n;

3 问题的解决
<1>直接用根据递推公式建立递归函数
这样的缺点就是会重复计算价值,造成资源的浪费
<2>建立起包含价值数组的递归函数
这是针对<1>的缺点,加入了价值数组,那么在用到长度为n的最大价值时候,如果r[n]已经存在,就不需要再次求解
<3>自底向上的迭代方法求解
这个比较简单和容易实现,它是不断的根据已经有的解来求解未知的解,从而得到最终的答案


4 代码实现
#include <iostream>#include <algorithm>#include <vector>int cutRod(int* p, int n);int memoryCutRod(int* p, int n);int memoryCutRodAux(int* p, int n, std::vector<int>& r);int bottomUpCutRod(int*p, int n);int main(){int p[10] = {1,5,8,9,10,17,17,20,24,30};int n = 4;//first methodint r = cutRod(p, 4);std::cout << "max r:" << r << std::endl;//second methodr = memoryCutRod(p,4);std::cout << "max r:" << r << std::endl;//third mehodr = bottomUpCutRod(p, 4);std::cout << "max r:" << r << std::endl;return 0;}int cutRod(int* p, int n){if (n == 0)return 0;int q = INT_FAST32_MIN;for (int i = 1; i <= n; i++){q = std::max(q, p[i-1] + cutRod(p, n-i));}return q;}int memoryCutRod(int* p, int n){std::vector<int> r(n + 1, INT_FAST32_MIN);return memoryCutRodAux(p, n, r);}int memoryCutRodAux(int* p, int n, std::vector<int>& r){if (r[n] >= 0)return r[n];int q = INT_FAST32_MIN;if (n == 0)q = 0;else{for (int i = 1; i <= n; i++)q = std::max(q, p[i-1] + memoryCutRodAux(p, n-i, r));}r[n] = q;return q;}int bottomUpCutRod(int*p, int n){std::vector<int> r(n + 1, INT_FAST32_MIN);r[0] = 0;for (int j = 1; j <= n; j++){int q = INT_FAST32_MIN;for (int i = 1; i <= j; i++){q = std::max(q, p[i-1] + r[j-i]);}r[j] = q;}return r[n];}


5 输出

max r:10
max r:10
max r:10

6 参考

算法导论

0 0
原创粉丝点击