Суммируйте все комбинации в векторе

0

Я пытаюсь вычислить сумму всех возможных комбинационных чисел в векторе. Если комбинация равна заданному числу, функция возвращает false. Если никакая комбинация не равна этому числу, массив печатает число и возвращает true.

Это то, что у меня есть:

bool t(vector<int>vi, int num){
  for(int i = 0; i < vi.size(); i++) {
    int sum=vi[i];
    for(int j = i+1; j < d.size(); j++) {
      if(sum + vi[j] == num) return false;
    }
  }
  cout<< num << endl;
  return true;
}

Как вы можете видеть, я могу рассчитать один уровень сумм чисел с учетом корневой точки, но я застрял там, где мне нужно продолжить ветвление выше. Кажется, что если бы этот метод вызывал сам себя и рекурсивно продвигался по веткам, но я не могу понять, как это сделать.

  • 0
    Я нашел несколько решений для SO, которые включали определение типов, но я уверен, что это можно сделать с существующими типами.
  • 0
    ваша сумма и переменная х совпадают?
Показать ещё 5 комментариев
Теги:

2 ответа

1
Лучший ответ

Рекурсия - отличный способ решить эту проблему.

bool t_helper(vector<int>::const_iterator it, vector<int>::const_iterator end, int sum_left)
{
    if (sum_left == 0) return false;
    if (it == end) return true;
    return t_helper(it+1, end, sum_left - *it) && t_helper(it+1, end, sum_left);
}

bool t(const vector<int>& vi, int num)
{
    bool result = t_helper(vi.begin(), vi.end(), num);
    if (result) cout << num << endl;
    return result;
}

Если вы знаете что-то лишнее, вы можете рано выйти. Например, если элементы vi неотрицательны, то если sum_left становится отрицательным, вы можете пропустить остальную часть этой ветки. Такие методы "обрезки" часто делают такой подход быстрее, чем исчерпывающая итерация.

Еще одно предложение обрезки - вернуть другое значение, когда включение всех положительных элементов на ветке (и только положительные элементы) не соответствует цели. Это означает, что подмножество также не может достичь цели.

  • 0
    Мои текущие цели никогда не будут иметь отрицательного числа в массиве, но я могу использовать это позже.
  • 0
    Кстати, как вы получаете sum_left в t() даже не объявив его?
Показать ещё 2 комментария
1

Математически вы можете сделать это итеративно, представив массив как двоичную строку длины n. При каждом индексе он равен 1 или 0. Если оно равно 1, то мы добавляем его в сумму, а если оно равно 0, мы исключаем его из суммы.

Все, что вам нужно сделать, - пройти через каждую возможную длину n двоичной строки от 000....000 до 111....111 и суммировать в зависимости от того, какие индексы активированы.

Что касается прохождения всех возможных двоичных строк, вы можете иметь массив размером n который начинается со всех индексов, установленных в 0. Затем вы просто зацикливаете до тех пор, пока он не станет массивом со всеми индексами, установленными в 1. На каждой итерации цикла вы добавляете 1 к биту с индексом n - 1. Если этот бит равен 1, установите его в 0 и переносите и добавьте 1 в бит в позиции n - 2 и т.д. (Делая двоичное добавление).

  • 0
    И если n < 32 , вы можете использовать непосредственно uint32_t .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню