Легче ли решить этот вариант задачи о сумме подмножеств?

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

Учитывая значение V, размер набора L и последовательность чисел [1, N] S, сколько подмножеств размера L в сумме S меньше V?

Это отличается от задачи о сумме подмножества тремя способами:

  1. Меня волнует, сколько подмножеств меньше, чем заданное значение, а не сколько равный.
  2. Размеры подмножества фиксированы.
  3. Я забочусь о том, что сколько устанавливает сумму меньше V, а не только о том, существуют ли какие-либо.

Есть ли какой-нибудь достаточно эффективный алгоритм для решения этой проблемы?

Редактировать: Очевидно, это можно сделать за O (N выбрать L), используя алгоритм генерации комбинации. Что меня действительно интересует, так это умные хаки, которые значительно ускорят это.

Разве это не просто Задача о рюкзаке с изюминкой? Возможно, я ошибаюсь.

Lasse V. Karlsen 18.12.2008 00:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
1
7 611
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Одна оптимизация, которая приходит на ум, заключается в следующем: закажите последовательность (если это не так). Выберите первые элементы L-1 с его начала, а затем выберите последний элемент так, чтобы это было наибольшее возможное значение (следующее наибольшее значение в последовательности дало бы слишком большую сумму). Отбросьте остальную часть последовательности, потому что эти элементы в любом случае никогда не могут быть частью допустимого подмножества.

После этого, я думаю, снова полный поиск. Но опять же, возможны и другие оптимизации.

Ну, с одной стороны, поскольку вы указываете size = L, тогда, даже если вы не можете придумать ничего умного и просто использовать грубую силу, у вас будут (N выберите L) отдельные суммы в худшем случае, так что это немного лучше чем n ^^ L (ну, L + 1, так как вы затем суммируете каждое подмножество).

Это звучит как n выберите категорию проблемы. Генерация k-подмножеств n рассматривается в Руководстве по разработке алгоритмов Скиены, и книга предлагает перечислить соответствующие подмножества в лексикографическом порядке (например, рекурсивно). Затем проведите суммирование и сравнение каждого подмножества.

Если у вас есть отсортированный набор, вы, вероятно, можете исключить невозможные решения из области решений.

Я не готов представить доказательства, но похоже, что это может быть применимо к схеме динамического программирования: свести в таблицу список подмножеств размера 2, использовать их для компьютерных подмножеств размера 3 и т. д., Чтобы вам нужно было только изучить небольшая коллекция перспектив.

Ответ принят как подходящий

(Версия решения) ваша проблема все еще NP-полная. Идея состоит в том, что если бы мы могли решить вашу проблему, то (скажем, для каждого размера подмножества) мы могли бы спросить, сколько наборов в сумме меньше V, а сколько в сумме меньше V-1, и разница этих двух чисел будет скажите нам, есть ли подмножества, сумма которых равна V - таким образом, мы могли бы решить проблему суммы подмножеств. [Это не полное доказательство, потому что это Редукция по Тьюрингу, а не много одно сокращение.]

Однако есть простое решение динамическое программирование, которое выполняется за время O (nLV). [Причина, по которой это не доказывает, что P = NP, заключается в том, что V может быть экспоненциальным в размере ввода: с n битами вы можете представлять значения до 2n. Но если предположить, что ваш V не экспоненциальный, это не проблема.]

Пусть num [v] [k] [i] обозначает количество подмножеств размера k первых i элементов S, которые суммируются с v. Вы можете вычислить их как (для каждого i):

    num[0][0][i] = 1
    for v = 1 to V:
        for k = 1 to L:
            num[v][k][i] = num[v][k][i-1] + num[v-S[i]][k-1][i-1]

где S [i] - i-й элемент в вашей последовательности. (Любой набор размера k, который суммируется с v, либо не использует S [i], поэтому он учитывается в num [v] [k] [i-1], либо он использует S [i], что означает, что остальная часть подмножество имеет k-1 элементов, использует только первые числа i-1 в последовательности и суммирует vS [i].) Наконец, подсчитайте num [v] [L] [| S |] для каждого v меньше V ; это твой ответ.

Кроме того, вы можете опустить третий индекс, если будете делать это осторожно (запускайте цикл вниз для каждого i и т. д.); Я включил это только для ясности.

Решение динамического программирования для задачи суммы подмножества генерирует таблицу, которая содержит этот ответ (то есть логическую таблицу V на N, где V - максимальное количество элементов, а N - максимальное количество элементов, которые могут быть в наборе, который удовлетворяет ограничения; каждое логическое значение истинно, если сумма элементов <= N равна <= V). Итак, если N * V для вас не слишком велико, существует приемлемо быстрый алгоритм. Решение суммы подмножества - это просто самый высокий элемент набора в этой таблице, для которого количество элементов <= N / 2.

Если это только положительные целые числа, вы можете выполнить шаг проверки если тебе надо;

Возьмите сумму L-1 наименьших целых чисел в наборе. Если это сумма X, то n-X должно быть ниже самого большого элемента, если проблема предполагаемый, чтобы иметь решение. Если подумать, вы можете устранить другие L таким образом ...

Возможно, формулировка динамического программирования является частью PTAS FPTAS.

Другие вопросы по теме