| #pragma once |
| |
| #ifndef TCG_SEQUENCE_OPS_HPP |
| #define TCG_SEQUENCE_OPS_HPP |
| |
| #include "../sequence_ops.h" |
| |
| #ifdef min |
| #undef min |
| #endif |
| |
| namespace tcg { |
| namespace sequence_ops { |
| |
| |
| |
| |
| |
| template <typename ranit_type, typename edge_eval, typename containers_reader> |
| bool minimalPath(ranit_type begin, ranit_type end, edge_eval &eval, |
| containers_reader &output) { |
| typedef typename ranit_type::difference_type diff_type; |
| typedef typename edge_eval::penalty_type penalty_type; |
| |
| ranit_type a, b; |
| diff_type i, j, m, n = end - begin, last = n - 1; |
| |
| |
| |
| |
| std::vector<diff_type> furthest(n); |
| |
| diff_type currFurthest = furthest[last] = last; |
| for (i = last - 1; i >= 0; --i) { |
| currFurthest = furthest[i] = |
| std::min(eval.furthestFrom(begin + i) - begin, currFurthest); |
| if (currFurthest == i) |
| return false; |
| } |
| |
| |
| |
| |
| for (i = 0, m = 0; i < last; i = furthest[i], ++m) |
| ; |
| |
| |
| |
| |
| std::vector<diff_type> upperBound(m + 1); |
| |
| for (i = 0, j = 0; i <= m; j = furthest[j], ++i) upperBound[i] = j; |
| |
| |
| |
| std::vector<penalty_type> minPenaltyToEnd(n); |
| std::vector<diff_type> minPenaltyNext(last); |
| diff_type aIdx, bIdx; |
| penalty_type newPenalty; |
| |
| minPenaltyToEnd[last] = 0; |
| |
| diff_type nextLowerBound; |
| for (j = m - 1, nextLowerBound = last; j >= 0; --j) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| for (aIdx = upperBound[j]; aIdx >= 0 && furthest[aIdx] >= nextLowerBound; |
| --aIdx) { |
| a = begin + aIdx; |
| |
| |
| |
| minPenaltyToEnd[aIdx] = (std::numeric_limits<penalty_type>::max)(); |
| |
| for (bIdx = nextLowerBound, b = begin + nextLowerBound; |
| furthest[aIdx] >= bIdx; ++b, ++bIdx) { |
| assert(minPenaltyToEnd[bIdx] < |
| (std::numeric_limits<penalty_type>::max)()); |
| newPenalty = eval.penalty(a, b) + minPenaltyToEnd[bIdx]; |
| if (newPenalty < minPenaltyToEnd[aIdx]) { |
| minPenaltyToEnd[aIdx] = newPenalty; |
| minPenaltyNext[aIdx] = bIdx; |
| } |
| } |
| } |
| |
| |
| nextLowerBound = aIdx; |
| ++nextLowerBound; |
| } |
| |
| |
| output.openContainer(begin); |
| for (i = minPenaltyNext[0], j = 1; j < m; i = minPenaltyNext[i], ++j) |
| output.addElement(begin + i); |
| output.addElement(begin + last); |
| output.closeContainer(); |
| |
| return true; |
| } |
| } |
| } |
| |
| #endif |