2013-08-09 4 views
0

У меня типичный вопрос в динамическом программировании.Динамическое программирование с наборами

Мой вопрос задан для массива = {1,2,3,4,5,6}, я должен найти все массивы, сумма которых является самой большой k. Если я рассмотрю все множества, он станет экспоненциальным alogorthm. Я думал об этом благодаря Dynamic Programming.

Suppose f k =7, 
My idea is 
Pass 1: {1],{2}....{6} 
Pass 2: Pass1 + {1,2},{1,3},{1,4},{1,5} 
Pass 3: Pass2 + {1,2,3}, 

И мое слово останавливается.

Im не в состоянии сформулировать это с помощью динамического программирования. Любые входы? Как сформулировать этот алгоритм в программу?

+1

DP обычно используется, если существует такое подмножество или найти число таких подмножеств. Обратите внимание, что DP все еще будет экспоненциальным, если вы хотите, чтобы все сами наборы, потому что это может быть экспоненциальное число. – amit

+2

Каждый алгоритм для этой задачи обязательно является экспоненциальным в худшем случае, поскольку в решении может быть экспоненциально множество множеств (пусть k = sum (array), то вам нужно вернуть все 2^n подмножества). Может быть, вы хотите только подсчитать количество таких наборов? –

ответ

0

Ваша проблема - это пример knapsack problem, чья проблема с решением проблемы, как известно, является NP-полной. это означает, что, безусловно, не будет субэкспоненциального алгоритма (хотя математическое доказательство отсутствует).

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

Поскольку проблема решения NP-полная, подсчет не может быть проще (иначе вы бы посчитали и затем проверили результат, равный 0 или нет).

+0

Да, эта проблема явно NP-жесткая, но подсчет может быть «проще» в том, что, как и рюкзак, проблема может быть слабо полиномиальной. То есть, если k полиномиально по n, может существовать поли-временное решение. –

1
решение

DP-за проблемы должны следовать следующей рекурсивную формулу, и строить снизу вверх:

f(i,0) = {{}} //a set containing only an empty set 
f(0,W) = {{}} (W > 0) 
f(0,W) = {} (W < 0) //an empty set 
f(i,W) = f(i-1,W) [union] extend(f(i-1,w-element[i]),element[i]) 

где функция расширения (набор, е):

extend(set,e): 
    for each s in set: //s is a set itself 
     s.add(e) 

Обратите внимание, что сложность все еще может быть экспоненциальной (и даже не псевдополиномиальной), поскольку число сгенерированных множеств может быть экспоненциальным и храниться в таблице DP.

Смежные вопросы