int taken = 0;
for (int i = 0; i < n; ++i) {
if (rand()*(n-i) < k-taken) {
++taken;
// Взять элемент i.
}
}
Всё равно ж надо начинать с подсчёта общего веса и проверки, что оно вообще возможно, а также расчёта веса каждой кучки. А потом, используя ДП, набиваем один рюкзак, а по завершении второй.
ДП: Условия задач
в задачах где по условиям будет ограничено время/память данное решение не доберет по баллам,
но 4 цикла дороже одного, умножение дороже
умножение дороже и несет риск переполнения
но навскидку выглядит как набор антипаттернов.
Что значит текущих положений гирь? Такое текущее положение может быть в переборе, где у вас одно состояние рассматривается в каждый момент времени и чуть чуть туда-сюда меняется. Если у вас ДП, то у вас куча состояний и для каждого из них есть "местоположение гирь".
Если стостояние {сколько гирек обработали, сколько весит первая кучка, сколько весит вторая кучка} (как у автора вопроса), то достаточно хранить одно только число - в какой кучке лежит последняя из обработанных гирек. Чтобы восстановить все гири, надо эту последнюю выкинуть из рассмотрения, вычев ее из нужной кучки и повторить операцию уже в новом состоянии. Именно это описанно у меня в ответе ниже.
Но там все-равно есть трехмерный массив для всех стостояний.
Или вы предлагаете сделать его четырехмерным и хранить еще для каждой гирьки, где она лежит - куб из "текущих местоположений гирек"?