Проблема в NPC, но есть псевдополиномиальный алгоритм для нее, это 2-секционная проблема, вы можете следовать пути псевдополиномиального алгоритма времени для сумма подмножества проблема, чтобы решить это.Если входной размер полиномиально связан с входными значениями, то это можно сделать за полиномиальное время.
В вашем случае (вес <250) это полином (потому что вес <= 250 n => суммы <= 250 n ^ 2). </p>
Пусть Sum = сумма весов, мы должнысоздать двумерный массив A, затем построить A, Столбец по столбцу
A [i, j] = true, если (j == weight [i] или j - weight [i] = weight [k] (k)находится в списке)).
Создание массива с помощью этого алгоритма занимает O (n ^ 2 * sum / 2).
Наконец мы должны найти наиболее ценный столбец, который имеет истинное значение.
Вот пример:
пунктов: {0,1,2,3} весов: {4,7,2,8} => сумма = 21 сумма / 2 = 10
items/weights 0| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
---------------------------------------------------------
|0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0
|1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0
|2 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1
|3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1
Так как [10, 2] == true раздел равен 10, 11
Это алгоритм, который я нашел здесь и отредактировал немного, чтобырешить вашу проблему:
bool partition( vector< int > C ) {
// compute the total sum
int n = C.size();
int N = 0;
for( int i = 0; i < n; i++ ) N += C[i];
// initialize the table
T[0] = true;
for( int i = 1; i <= N; i++ ) T[i] = false;
// process the numbers one by one
for( int i = 0; i < n; i++ )
for( int j = N - C[i]; j >= 0; j--)
if( T[j] ) T[j + C[i]] = true;
for(int i = N/2;i>=0;i--)
if (T[i])
return i;
return 0;
}
Я только что возвратил первое T [i], которое является истинным, вместо того, чтобы возвращать T [N / 2] (от макс до мин).
Поиск путичто дает это значение не сложно.