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