算法导论第十五章-动态规划-Cpp代码实现

来源:互联网 发布:天狼星期货软件 编辑:程序博客网 时间:2024/04/30 11:46

算法导论第十五章-动态规划-Cpp代码实现。


实现了书中切钢条最大收益问题和经典算法最长公共子序列(LCS)的问题。

从递归,引出带备忘的自顶向下,自底向上等解法。


dynamic_programming.h

#pragma once/*************************************************Author:董小歪Date:2016-06-16Description:算法导论第十五章-动态规划-Cpp代码实现**************************************************/#ifndef DYNAMIC_PROGRAMMING_H#define DYNAMIC_PROGRAMMING_H#include <iostream>#include <vector>#include <algorithm>using namespace std;class Dynamic_Programming{public:int cut_rod(const vector<int> &p, int n);//递归算法int memorized_cut_rod(const vector<int>& p, int n);//带备忘的自顶向下法int bottom_up_cut_rod(const vector<int>& p, int n);//自底向上法vector<vector<int>> extended_button_up_cut_rod(const vector<int>& p, int n);//重构解void print_cut_rod_solution(const vector<int>& p, int n);//打印重构借vector<vector<int>> LCS_length(const vector<char>& vec1, const vector<char>& vec2);//LCSvoid print_LCS(const vector<vector<int>>& b, const vector<char>& vec1, int i, int j);//打印LCSprivate:int memorized_cut_aux(const vector<int>& p, int n, vector<int>& r);};#endif // !DYNAMIC_PROGRAMMING_H

dynamic_programming.cpp

#include "dynamic_programming.h"int Dynamic_Programming::cut_rod(const vector<int> &p, int n){if (n == 0)return 0;int q = INT_MIN;for (int i = 1; i <= n; ++i)q = max(q, p[i] + cut_rod(p, n - i));return q;}int Dynamic_Programming::memorized_cut_rod(const vector<int> &p, int n){vector<int> r(n + 1, INT_MIN);return memorized_cut_aux(p, n, r);}int Dynamic_Programming::memorized_cut_aux(const vector<int> &p, int n, vector<int>& r){if (r[n] >= 0)return r[n];int q = INT_MIN;if (n == 0)q = 0;else{for (int i = 1; i <= n; ++i)q = max(q, p[i] + memorized_cut_aux(p, n - i, r));}r[n] = q;return q;}int Dynamic_Programming::bottom_up_cut_rod(const vector<int>& p, int n){vector<int> r(n + 1, INT_MIN);r[0] = 0;for (int j = 1; j <= n; ++j){int q = INT_MIN;for (int i = 1; i <= j; ++i)q = max(q, p[i] + r[j - i]);r[j] = q;}return r[n];}vector<vector<int>> Dynamic_Programming::extended_button_up_cut_rod(const vector<int>& p, int n){vector<int> r(n + 1, 0), s(n + 1, 0);r[0] = 0;for (int j = 1; j <= n; ++j){int q = INT_MIN;for (int i = 1; i <= j; ++i){if (q < p[i] + r[j - i]){q = p[i] + r[j - i];s[j] = i;}}r[j] = q;}vector<vector<int>> ret;ret.push_back(r);ret.push_back(s);return ret;}void Dynamic_Programming::print_cut_rod_solution(const vector<int>& p, int n){vector<vector<int>> res = extended_button_up_cut_rod(p, n);for (int i = 0; i <= n; ++i){printf("r[%d] = %d, s[%d] = %d\n", i, res[0][i], i, res[1][i]);}}vector<vector<int>> Dynamic_Programming::LCS_length(const vector<char>& vec1, const vector<char>& vec2){int m = vec1.size(), n = vec2.size();vector<vector<int>> b(m + 1, vector<int>(n + 1, 0));vector<vector<int>> c(m + 1, vector<int>(n + 1, 0));for (int i = 1; i <= m; ++i){for (int j = 1; j <= n; ++j){if (vec1[i - 1] == vec2[j - 1]){c[i][j] = c[i - 1][j - 1] + 1;b[i][j] = 2;}else if (c[i - 1][j] >= c[i][j - 1]){c[i][j] = c[i - 1][j];b[i][j] = 3;}else{c[i][j] = c[i][j - 1];b[i][j] = 1;}}}return b;}void Dynamic_Programming::print_LCS(const vector<vector<int>>& b, const vector<char>& vec1, int i, int j){if (i == 0 || j == 0)return;if (b[i][j] == 2){print_LCS(b, vec1, i - 1, j - 1);cout << vec1[i-1];}else if (b[i][j] == 3)print_LCS(b, vec1, i - 1, j);elseprint_LCS(b, vec1, i, j - 1);}

测试代码:

main_entrance.cpp

#include "dynamic_programming.h"int main(){vector<int> p = { 0,1,5,8,9,10,17,17,20,24,30 };printf("钢条的价格表:\n长度i:\t1\t2\t3\t4\t5\t6\t7\t8\t9\t10\n");printf("价格pi:%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n\n",p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10]);Dynamic_Programming dp;cout << "递归算法:长度为4的钢条最大收益为:" << dp.cut_rod(p, 4) << endl;cout << "递归算法:长度为10的钢条最大收益为:" << dp.cut_rod(p, 10) << endl;cout << "自顶向下:长度为4的钢条最大收益为:" << dp.memorized_cut_rod(p, 4) << endl;cout << "自顶向下:长度为10的钢条最大收益为:" << dp.memorized_cut_rod(p, 10) << endl;cout << "自底向上:长度为4的钢条最大收益为:" << dp.bottom_up_cut_rod(p, 4) << endl;cout << "自底向上:长度为10的钢条最大收益为:" << dp.bottom_up_cut_rod(p, 10) << endl;cout << "自底向上切割的方法,长度10内的结果,r[i]表示最大收益,s[i]表示当前最大收益下的第一段切割长度:" << endl; dp.print_cut_rod_solution(p, 10);vector<char> vec1 = { 'A','B','C','B','D','A','B' };vector<char> vec2 = { 'B','D','C','A','B','A' };cout << endl << "串1序列是:";for (auto ch : vec1)cout << ch;cout << endl << "串2序列是:";for (auto ch : vec2)cout << ch;cout << endl << "最长公共子序列是:" << endl;dp.print_LCS(dp.LCS_length(vec1, vec2), vec1, vec1.size(), vec2.size());cout << endl;system("pause");}

测试结果:


0 0
原创粉丝点击