Brute Force Seam Carving
Brute Force Seam Carving
#define NUM_BASE_CHILD 3
#define NUM_EDGE_CHILD 2
struct Node {
Node(const int act_val, int accum_val, const int r, const int c, const int num_child, Node *parent)
: actual_val(act_val), r(r), c(c), accum_val(accum_val), parent(parent) {
children.reserve(num_child);
for (int i = 0; i < num_child; i++) {
children.push_back(nullptr);
}
}
const int r, c;
const int actual_val;
int accum_val;
vector<Node*> children;
Node *parent;
};
class Nary_tree {
public:
Nary_tree(const vector<vector<int>> &m)
: matrix(m) {
root = new Node(INT_MIN, INT_MIN, INT_MIN, INT_MIN, 0, nullptr);
}
void create_bf_tree()
{
// initialize root with child nodes
int r = 0;
for (int c = 0; c < matrix.size(); c++) {
if (c > 0 && c > matrix.size())
root->children.push_back(new Node(matrix[r][c], matrix[r][c], r, c, NUM_BASE_CHILD, root));
else
root->children.push_back(new Node(matrix[r][c], matrix[r][c], r, c, NUM_EDGE_CHILD, root));
}
for (int c = 0; c < matrix.at(0).size(); c++) {
create_bf_tree_rec(root->children[c]);
}
}
vector<Node*> backtrack_minimum_path()
{
vector<Node*> min_path;
Node *iter = *min_element(leaf_nodes.begin(), leaf_nodes.end(),
[](const Node* l, const Node* r) {
return l->accum_val < r->accum_val;
});
while (iter->parent != nullptr) {
min_path.push_back(iter);
iter = iter->parent;
}
return min_path;
}
void print_attributes(vector<Node*> &stuff)
{
for (Node *n : stuff) {
cout << setw(21) << "Row value: " << n->r << endl;
cout << setw(21) << "Col value: " << n->c << endl;
cout << setw(21) << "Actual value: " << n->actual_val << endl;
cout << setw(21) << "Accumulated value: " << n->accum_val << endl;
cout << endl;
}
cout << endl;
}
void pre_order_traversal()
{
pre_order_traversal_rec(root);
}
private:
const vector<vector<int>> matrix;
vector<Node*> leaf_nodes;
Node *root;
// tree is built in a preorder fashion
void create_bf_tree_rec(Node *parent)
{
// | - center - |
if (parent->c > 0 && parent->c < matrix.at(0).size() - 1 && parent->r < matrix.size() - 1) {
for (int i = 0; i < NUM_BASE_CHILD; i++) {
int new_r = parent->r + 1;
int new_c = parent->c + i - 1;
int sum_val = parent->accum_val +
matrix[new_r][new_c];
Node *temp = new Node(matrix[new_r][new_c], sum_val, new_r, new_c, NUM_BASE_CHILD, parent);
create_bf_tree_rec(temp);
// create link and
// check for leaf node for later processing
parent->children.push_back(temp);
if (parent->r == matrix.size() - 2) {
leaf_nodes.push_back(temp);
}
}
}
// | - left end
else if (parent->c == 0 && parent->r < matrix.size() - 1) {
for (int i = 0; i < NUM_EDGE_CHILD; i++) {
int new_r = parent->r + 1;
int new_c = parent->c + i;
int sum_val = parent->accum_val +
matrix[new_r][new_c];
Node *temp = new Node(matrix[new_r][new_c], sum_val, new_r, new_c, NUM_EDGE_CHILD, parent);
create_bf_tree_rec(temp);
parent->children.push_back(temp);
if (parent->r == matrix.size() - 2) {
leaf_nodes.push_back(temp);
}
}
}
// right end - |
else if (parent->c == matrix.at(0).size() - 1 && parent->r < matrix.size() - 1) {
for (int i = 0; i < NUM_EDGE_CHILD; i++) {
int new_r = parent->r + 1;
int new_c = parent->c + i - 1;
int sum_val = parent->accum_val +
matrix[new_r][new_c];
Node *temp = new Node(matrix[new_r][new_c], sum_val, new_r, new_c, NUM_EDGE_CHILD, parent);
create_bf_tree_rec(temp);
parent->children.push_back(temp);
if (parent->r == matrix.size() - 2) {
leaf_nodes.push_back(temp);
}
}
}
}
void pre_order_traversal_rec(Node *root)
{
if (root) {
cout << root->actual_val << ", ";
for (Node *i : root->children) {
pre_order_traversal_rec(i);
}
}
}
};
int main()
{
vector<vector<int>> matrix = { { 1, 3, 0},
{ 2, 8, 9 },
{ 5, 2, 6 }, };
Nary_tree mytree(matrix);
mytree.create_bf_tree();
vector<Node*> bc = mytree.backtrack_minimum_path();
mytree.print_attributes(bc);
mytree.pre_order_traversal();
getchar();
}Dynammic Programming Approach
Last updated