(версия решения) ваша проблема все еще NP-завершена. Идея состоит в том, что если бы мы могли решить вашу проблему, то (скажем, для каждого размера подмножества) мы могли бы спросить, сколько наборов сумма меньше V и сколько сумма меньше V-1, и разница между этими двумя числами скажите нам, являются ли подмножества суммирующими в точности V - таким образом, мы могли бы решить проблему сумм подмножеств. [Это не полное доказательство, потому что это сокращение Тьюринга , а не много одно сокращение .]
Однако существует простое решение для динамического программирования , которое выполняется за время O (nLV). [Причина, по которой это не доказывает, что P = NP, состоит в том, что V может быть экспоненциальным по входному размеру: с n битами вы можете представлять значения до 2 n . Но если предположить, что ваш V не экспоненциальный, это не проблема.]
Пусть num [v] [k] [i] обозначает количество подмножеств size-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 и т. Д.); Я включил его только для ясности.