Разбить множество чисел на подмножества, разница сумм которых минимальна и вывести на экран эту разницу.
Для решения этой задачи будем использовать динамическое программирование.
Не сложно понять, что сумма каждого из двух выбранных множеств должна быть как можно "ближе" к половине суммы всего исходного множества т.е. если представить сумму всего исходного множества за C, а суммы двух выбранных подмножеств за A и B, то:
A + B = C;
A ~ C / 2
B ~ C / 2
И так, задача сводится к нахождению подмножества с суммой C/2.
Почитайте это
Перейдём к реализации.
Так как каждую вещь можно брать только один раз, то будем идти не слева направо, а справа налево.
Будем хранить 1 или 0, что значит можно ли достичь суммы M, если взять N предметов.
0 <= M <= C/2
Ответом будет ячейка таблицы отмеченная как 1 и с максимальной M (т.к. нам нужно взять набранную сумму как можно ближе к C/2)
Для решения этой задачи будем использовать динамическое программирование.
Не сложно понять, что сумма каждого из двух выбранных множеств должна быть как можно "ближе" к половине суммы всего исходного множества т.е. если представить сумму всего исходного множества за C, а суммы двух выбранных подмножеств за A и B, то:
A + B = C;
A ~ C / 2
B ~ C / 2
И так, задача сводится к нахождению подмножества с суммой C/2.
Почитайте это
Перейдём к реализации.
Будем хранить 1 или 0, что значит можно ли достичь суммы M, если взять N предметов.
0 <= M <= C/2
Ответом будет ячейка таблицы отмеченная как 1 и с максимальной M (т.к. нам нужно взять набранную сумму как можно ближе к C/2)
#include <iostream>#include <vector> #include <cmath> #define REP(i,n) for (int i = 0; i < n; i++) using namespace std; bool f[100]; int main() { int n; long sum = 0; cin >> n; vector<int> v(n); REP(i,n) cin >> v[i], sum += v[i]; int m = sum/2; int w = 0; f[0] = 1; for (int i = n-1; i >= 0; i--) { for (int j = m; j >= 0; j--) { if (f[j] == 1) { f[j+v[i]] = 1; } } } for (int i=m;i>=0;i--) if (f[i]) { w=i; break; } cout << abs(w-(sum-w)) << endl; return 0; }
No comments :
Post a Comment