Я новичок в программировании Dynami c и придумал свой (очевидно неправильный) подход к проблеме подмножества суммы. Хотелось бы узнать, почему мой подход неверен. В частности, мне любопытно, верна ли основная идея вообще, или я должен просто придерживаться обычного подхода к сумме подмножества см. Yt .
Проблема: Учитывая массив чисел, найдите в нем 2 подмножества, которые имеют одинаковую сумму. Эта проблема немного изменена по сравнению с обычной проблемой суммы подмножеств.
Пример: [1,5,5,9]
можно разделить на [1,9]
и [5,5]
.
Идея:
1 5 5 9
0 5 5 9
1 1 6 6 10
5 6 5 6 10
5 6 10 10 10
9 6 10 10 10
Вместо того, чтобы отслеживать, какие элементы я беру, а какие нет (как обычно), я хотел бы отслеживать сумму. Идея состоит в том, чтобы найти сумму предыдущих элементов в mem[i-1][j]
(один над текущей позицией). Если это значение + текущее значение меньше или равно половине общей суммы (в данном случае 20), мы добавляем текущее значение к сумме. В противном случае мы просто берем предыдущее значение и игнорируем текущее значение.
Элементы, расположенные по диагонали в таблице, будут только сами по себе. Я делаю это, потому что в противном случае я бы добавил один и тот же элемент дважды.
В этом примере алгоритм завершится, когда увидит первые 10.
Реализация:
Играйте с кодом
bool has_solution(std::vector<int> &v) {
const long long sum = accumulate(v.begin(), v.end(), 0);
long long mem[v.size() + 1][v.size()];
for (int j = 0; j < v.size(); ++j) {
mem[0][j] = v.at(j);
}
mem[0][0] = 0;
for(int i = 1; i < v.size(); ++i) {
for (int j = 0; j < v.size(); ++j) {
if (i - 1 == j) {
mem[i][j] = v.at(i - 1);
} else {
const long long new_sum = mem[i - 1][j] + v.at(i - 1) ;
if (new_sum <= sum - new_sum) {
mem[i][j] = new_sum;
} else {
mem[i][j] = mem[i - 1][j];
}
}
if (mem[i][j] * 2 == sum) {
return true;
}
}
}
return false;
}
Алгоритм дает неверное решение для ввода [987, 856, 743, 491, 227, 365, 859, 936, 432, 551, 437, 228, 275, 407, 474]
. Он должен возвращать истину, но возвращает ложь, согласно site .