算法导论 第三版 15.4动态规划问题
升级到vs2012 update1, 结果仍然没有C++11的初始化列表功能, 测试函数里面给vector添加data就比较丑了。
//longest common subsequence introduction to algorithm 3rd, example 15.3
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
#include <ostream>
#include <iterator>
#include <limits>
#include <complex>
#include "stopwatch.h"
struct Record
{
enum Direction
{
eUnknown = 0,
eMatch,
eMoveV1,
eMoveV2,
};
Record () : max(std::numeric_limits<size_t>::max()), direction(eUnknown) {}
// I get bug here, to avoid it, use explicit type conversion
operator bool() {return max != std::numeric_limits<rsize_t>::max();}
size_t max;
Direction direction;
};
template <typename value_t>
size_t compute_lcs(const std::vector<value_t> & v1, size_t pv1, const std::vector<value_t> & v2, size_t pv2, std::vector<std::vector<Record>> & solution)
{
if (solution[pv1][pv2])
{
return solution[pv1][pv2].max;
}
size_t max = 0;
if (v1[pv1] == v2[pv2])
{
max = 1 + ((pv1 && pv2) ? compute_lcs(v1, pv1-1, v2, pv2-1, solution) : 0);
solution[pv1][pv2].max = max;
solution[pv1][pv2].direction = Record::eMatch;
}
else
{
auto v1max = pv2 ? compute_lcs(v1, pv1, v2, pv2-1, solution) : 0;
auto v2max = pv1 ? compute_lcs(v1, pv1-1, v2, pv2 , solution) : 0;
max = std::max(v1max, v2max);
solution[pv1][pv2].max = max;
solution[pv1][pv2].direction = v1max > v2max ? Record::eMoveV2 : Record::eMoveV1;
}
return max;
}
template <typename value_t>
size_t compute_lcs_none_recursive(const std::vector<value_t> & v1, const std::vector<value_t> & v2, std::vector<std::vector<Record>> & solution)
{
for (size_t iv1 = 0; iv1 < v1.size(); ++iv1)
{
for (size_t iv2 = 0; iv2 < v2.size(); ++iv2)
{
if (v1[iv1] == v2[iv2])
{
solution[iv1][iv2].max = iv1 && iv2 ? solution[iv1-1][iv2-1].max + 1 : 1;
solution[iv1][iv2].direction = Record::eMatch;
}
else
{
auto v1max = iv2 ? solution[iv1][iv2-1].max : 0;
auto v2max = iv1 ? solution[iv1-1][iv2].max : 0;
solution[iv1][iv2].max = std::max(v1max, v2max);
solution[iv1][iv2].direction = v1max > v2max ? Record::eMoveV2 : Record::eMoveV1;
}
}
}
return solution[v1.size()-1][v2.size()-1].max;
}
template <typename value_t>
void print_solution(const std::vector<value_t> & v1, const std::vector<std::vector<Record>> & solution, size_t p1, size_t p2)
{
switch (solution[p1][p2].direction)
{
default:
assert(false && "unexpected");
case Record::eUnknown:
break;
case Record::eMatch:
if (p1 && p2)
{
print_solution(v1, solution, p1-1, p2-1);
}
std::cout << v1[p1];
break;
case Record::eMoveV1:
if (p1)
{
print_solution(v1, solution, p1-1, p2);
}
break;
case Record::eMoveV2:
if (p2)
{
print_solution(v1, solution, p1, p2-1);
}
break;
}
}
template <typename value_t>
void compute_lcs(const std::vector<value_t> & v1, const std::vector<value_t> & v2)
{
std::vector<std::vector<Record>> solution(v1.size());
for (auto & i : solution)
{
i.resize(v2.size());
}
Stopwatch watch;
watch.start();
auto max_len = compute_lcs(v1, v1.size()-1, v2, v2.size()-1, solution);
watch.stop();
std::cout << "find the longest subsequence length " << max_len << " use time " << watch.elapsed() << " ms" << std::endl;
std::cout << "the solution is :\n";
print_solution(v1, solution, v1.size()-1, v2.size()-1);
}
template <typename value_t>
void compute_lcs_none_recursive(const std::vector<value_t> & v1, const std::vector<value_t> & v2)
{
std::vector<std::vector<Record>> solution(v1.size());
for (auto & i : solution)
{
i.resize(v2.size());
i[0].max = 0;
}
for (auto & i : solution[0])
{
i.max = 0;
}
Stopwatch watch;
watch.start();
auto max_len = compute_lcs_none_recursive(v1, v2, solution);
watch.stop();
std::cout << "none recursive find the longest subsequence length " << max_len << " use time " << watch.elapsed() << " ms" << std::endl;
std::cout << "the solution is :\n";
print_solution(v1, solution, v1.size()-1, v2.size()-1);
}
void test1()
{
std::vector<char> v1;
v1.reserve(7);
v1.push_back('A');
v1.push_back('B');
v1.push_back('C');
v1.push_back('B');
v1.push_back('D');
v1.push_back('A');
v1.push_back('B');
std::vector<char> v2;
v2.reserve(6);
v2.push_back('B');
v2.push_back('D');
v2.push_back('C');
v2.push_back('A');
v2.push_back('B');
v2.push_back('A');
std::cout << "test 1 : ";
std::copy(v1.begin(), v1.end(), std::ostream_iterator<char>(std::cout, ""));
std::cout << " and ";
std::copy(v2.begin(), v2.end(), std::ostream_iterator<char>(std::cout, ""));
std::cout << "\nthe expected answer is :\nBCBA" << std::endl;
compute_lcs(v1, v2);
std::cout << std::endl;
compute_lcs_none_recursive(v1, v2);
std::cout << std::endl;
}
void test2()
{
std::vector<char> v1;
v1.reserve(29);
// ACCG GTCG AGTG CGCG GAAG CCGG CCGAA
v1.push_back('A');
v1.push_back('C');
v1.push_back('C');
v1.push_back('G');
v1.push_back('G');
v1.push_back('T');
v1.push_back('C');
v1.push_back('G');
v1.push_back('A');
v1.push_back('G');
v1.push_back('T');
v1.push_back('G');
v1.push_back('C');
v1.push_back('G');
v1.push_back('C');
v1.push_back('G');
v1.push_back('G');
v1.push_back('A');
v1.push_back('A');
v1.push_back('G');
v1.push_back('C');
v1.push_back('C');
v1.push_back('G');
v1.push_back('G');
v1.push_back('C');
v1.push_back('C');
v1.push_back('G');
v1.push_back('A');
v1.push_back('A');
std::vector<char> v2;
v2.reserve(28);
// GTCG TTCG GAAT GCCG TTGC TCTG TAAA
v2.push_back('G');
v2.push_back('T');
v2.push_back('C');
v2.push_back('G');
v2.push_back('T');
v2.push_back('T');
v2.push_back('C');
v2.push_back('G');
v2.push_back('G');
v2.push_back('A');
v2.push_back('A');
v2.push_back('T');
v2.push_back('G');
v2.push_back('C');
v2.push_back('C');
v2.push_back('G');
v2.push_back('T');
v2.push_back('T');
v2.push_back('G');
v2.push_back('C');
v2.push_back('T');
v2.push_back('C');
v2.push_back('T');
v2.push_back('G');
v2.push_back('T');
v2.push_back('A');
v2.push_back('A');
v2.push_back('A');
std::cout << "test 2 : ";
std::copy(v1.begin(), v1.end(), std::ostream_iterator<char>(std::cout, ""));
std::cout << " and ";
std::copy(v2.begin(), v2.end(), std::ostream_iterator<char>(std::cout, ""));
std::cout << "\nthe expected answer is :\nGTCGTCGGAAGCCGGCCGAA" << std::endl;
compute_lcs(v1, v2);
std::cout << std::endl;
compute_lcs_none_recursive(v1, v2);
std::cout << std::endl;
}
class Value
{
public:
Value(int a) : mValue(a) {}
bool operator==(const Value & r) const {return mValue == r.mValue;}
private:
friend std::ostream & operator<<(std::ostream & os, const Value & value);
int mValue;
};
std::ostream & operator<<(std::ostream & os, const Value & value)
{
os << value.mValue;
return os;
}
void test3()
{
std::vector<Value> v1;
v1.reserve(7);
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(2);
v1.push_back(4);
v1.push_back(1);
v1.push_back(2);
std::vector<Value> v2;
v2.reserve(6);
v2.push_back(2);
v2.push_back(4);
v2.push_back(3);
v2.push_back(1);
v2.push_back(2);
v2.push_back(1);
std::cout << "test 3 : ";
std::copy(v1.begin(), v1.end(), std::ostream_iterator<Value>(std::cout, ""));
std::cout << " and ";
std::copy(v2.begin(), v2.end(), std::ostream_iterator<Value>(std::cout, ""));
std::cout << "\nthe expected answer is :\nBCBA" << std::endl;
compute_lcs(v1, v2);
std::cout << std::endl;
compute_lcs_none_recursive(v1, v2);
std::cout << std::endl;
}
int main()
{
std::cout << "start" << std::endl;
test1();
std::cout << std::endl;
test2();
std::cout << std::endl;
test3();
return 0;
}