Problem p03128 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cstdio>
#include <deque>
#include <functional>
#include <memory>
#include <tuple>
#include <vector>

using namespace std;

using ll = long long;
int n, m;
int digits[9];
int sticks_for_digits[10] = {-1, 2, 5, 5, 4, 5, 6, 3, 7, 6};
bool called[10000];
bool reachable[10000];

struct Node {
  int value;
  shared_ptr<Node> next;
  Node(int v, shared_ptr<Node> n) : value(v), next(n){};
};
struct LinkedList {
  shared_ptr<Node> root;
  int length;
  LinkedList() : length(0){};
  LinkedList(int v, LinkedList &tail)
      : length(tail.length + 1), root(make_shared<Node>(v, tail.root)){};
  bool empty() { return length == 0; }
  int size() { return length; }
};
const LinkedList nil;
LinkedList cons(int value, LinkedList &list) { return LinkedList(value, list); }
LinkedList dp[10000];

bool is_left_ge(LinkedList &left, LinkedList &right) {
  if (left.length > right.length)
    return true;
  if (left.length < right.length)
    return false;
  shared_ptr<Node> l = left.root;
  shared_ptr<Node> r = right.root;
  while (!((l == nullptr) && (r == nullptr))) {
    if (l->value > r->value)
      return true;
    if (l->value < r->value)
      return false;
    l = l->next;
    r = r->next;
  }
  return true;
}

void solve(int sticks) {
  if (called[sticks])
    return;
  called[sticks] = true;
  LinkedList cur;
  // printf("entering solve(%d)\n", sticks);
  // cur.push_back(0);
  for (int i = 0; i < m; i++) {
    int to_consume = sticks_for_digits[digits[i]];
    if (sticks < to_consume)
      continue;
    solve(sticks - to_consume);
    /*printf("solve(%d) =", sticks-to_consume);
    Node *ptr = dp[sticks-to_consume];
    while (ptr) {
      printf("%d", ptr->value);
      ptr = ptr->next;
    }
    printf("\n");*/
    if (!reachable[sticks - to_consume])
      continue;
    LinkedList newlist = cons(digits[i], dp[sticks - to_consume]);
    if (is_left_ge(newlist, cur)) {
      cur = newlist;
    }
  }
  if (cur.length == 0) {
    int c = 0;
    for (int i = 0; i < m; i++) {
      if (sticks_for_digits[digits[i]] == sticks) {
        c = max(c, digits[i]);
      }
    }
    if (c != 0) {
      cur = cons(c, cur);
    }
  } else if (cur.length == 1) {
    for (int i = 0; i < m; i++) {
      if (sticks_for_digits[digits[i]] == sticks) {
        cur.root->value = max(cur.root->value, digits[i]);
      }
    }
  }
  if (cur.length != 0) {
    dp[sticks] = cur;
    reachable[sticks] = true;
  }
}

int main() {
  scanf("%d %d", &n, &m);
  for (int i = 0; i < m; i++) {
    scanf("%d", &(digits[i]));
    // int sticks = sticks_for_digits[digits[i]];
    // digits_for_sticks[sticks] = max(digits_for_sticks[sticks], digits[i]);
  }
  reachable[0] = true;
  called[0] = true;
  dp[0] = LinkedList();
  solve(n);
  shared_ptr<Node> ptr = dp[n].root;
  vector<int> ds;
  while (ptr) {
    ds.push_back(ptr->value);
    ptr = ptr->next;
  }
  for (auto d : ds) {
    printf("%d", d);
  }
  printf("\n");
  return 0;
}


Fixed submission:
#include <algorithm>
#include <cstdio>
#include <deque>
#include <functional>
#include <memory>
#include <tuple>
#include <vector>

using namespace std;

using ll = long long;
int n, m;
int digits[9];
int sticks_for_digits[10] = {-1, 2, 5, 5, 4, 5, 6, 3, 7, 6};
bool called[10000];
bool reachable[10000];

struct Node {
  int value;
  shared_ptr<Node> next;
  Node(int v, shared_ptr<Node> n) : value(v), next(n){};
};
struct LinkedList {
  shared_ptr<Node> root;
  int length;
  LinkedList() : length(0){};
  LinkedList(int v, LinkedList &tail)
      : length(tail.length + 1), root(make_shared<Node>(v, tail.root)){};
  bool empty() { return length == 0; }
  int size() { return length; }
};
LinkedList nil;
LinkedList cons(int value, LinkedList &list) { return LinkedList(value, list); }
LinkedList dp[10000];

bool is_left_ge(LinkedList &left, LinkedList &right) {
  if (left.length > right.length)
    return true;
  if (left.length < right.length)
    return false;
  shared_ptr<Node> l = left.root;
  shared_ptr<Node> r = right.root;
  while (!((l == nullptr) && (r == nullptr))) {
    if (l->value > r->value)
      return true;
    if (l->value < r->value)
      return false;
    l = l->next;
    r = r->next;
  }
  return true;
}

void solve(int sticks) {
  if (called[sticks])
    return;
  called[sticks] = true;
  LinkedList cur;
  // printf("entering solve(%d)\n", sticks);
  // cur.push_back(0);
  for (int i = 0; i < m; i++) {
    int to_consume = sticks_for_digits[digits[i]];
    if (sticks < to_consume)
      continue;
    solve(sticks - to_consume);
    /*printf("solve(%d) =", sticks-to_consume);
    Node *ptr = dp[sticks-to_consume];
    while (ptr) {
      printf("%d", ptr->value);
      ptr = ptr->next;
    }
    printf("\n");*/
    if (!reachable[sticks - to_consume])
      continue;
    LinkedList newlist = cons(digits[i], dp[sticks - to_consume]);
    if (is_left_ge(newlist, cur)) {
      cur = newlist;
    }
  }
  if (cur.length == 0) {
    int c = 0;
    for (int i = 0; i < m; i++) {
      if (sticks_for_digits[digits[i]] == sticks) {
        c = max(c, digits[i]);
      }
    }
    if (c != 0) {
      cur = cons(c, cur);
    }
  } else if (cur.length == 1) {
    for (int i = 0; i < m; i++) {
      if (sticks_for_digits[digits[i]] == sticks) {
        cur.root->value = max(cur.root->value, digits[i]);
      }
    }
  }
  if (cur.length != 0) {
    dp[sticks] = cur;
    reachable[sticks] = true;
  }
}

int main() {
  scanf("%d %d", &n, &m);
  for (int i = 0; i < m; i++) {
    scanf("%d", &(digits[i]));
    // int sticks = sticks_for_digits[digits[i]];
    // digits_for_sticks[sticks] = max(digits_for_sticks[sticks], digits[i]);
  }
  reachable[0] = true;
  called[0] = true;
  dp[0] = LinkedList();
  solve(n);
  shared_ptr<Node> ptr = dp[n].root;
  vector<int> ds;
  while (ptr) {
    ds.push_back(ptr->value);
    ptr = ptr->next;
  }
  for (auto d : ds) {
    printf("%d", d);
  }
  printf("\n");
  return 0;
}