Какой алгоритм составить для подбора количества банок?

Здравствуйте!
Исходные данные: объем материала, банки разного объема.
К примеру, нам нужно 33 кг краски. У нас есть одна банка 15 кг и одна банка 7 кг.
Задача подсчитать какое количество и каких банок нам нужно.

Можно взять две по 15 кг и одну 7 кг - 37 кг. Это допустимо, превысить необходимый объем разрешается.
Можно взять пять по 7 кг.

Желательно выбрать первым делом банки максимального объема (в примере это 15 кг), потом банки меньшего и меньшего до тех пор, пока не наберем все банки)
  • Вопрос задан
  • 215 просмотров
Решения вопроса 1
@reaget Автор вопроса
У меня получилось такое решение. Спасибо большое, что приняли участие и помогли наставлениями :)
var n = 31;
var cans = [10, 15].sort(); // по возрастанию
var res = {};

while (n > 0) {
	let count = -1;
	for (let c in cans) {
		if (cans[c] < n) {
			count++;
		}
		else {
			count++;
			break;
		}
	}

	if (count < 0)
		continue;

	if (!res[ cans[count] ]) res[ cans[count] ] = 0;

	res[ cans[count] ]++;
	n -= cans[count];
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
sergiks
@sergiks Куратор тега Алгоритмы
♬♬
это называется «задача об упаковке» (packing problem) и решается полным перебором всех вариантов.

«Желательно» – это доп. условие, задающее «вес» разным вариантам.
Надо сформулировать функцию потерь: на входе комбинация банок, на выходе «штраф» за неё, который складывается из объёма перебора (недобор не должен вообще приходить), и, может, из количества мелких банок (чтобы минимизировать его).
Перебирая все варианты, считать штрафы, оставлять варианты с минимальными штрафами.

Несколько интересных алгоритмов. См. там ещё ссылки слева.
Ответ написан
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Задача логарифмической сложности.
Решается через генетический алгоритм с помощью перестановок.
Точка.
Ответ написан
Комментировать
john36allTa
@john36allTa
alien glow of a dirty mind
Пример простой реализации(есть недочёты) на JS, но можно адаптировать на любой в принципе..
function wrap(liquid, cans){
  let result = []
  cans = cans.sort((a,b) => b - a)
  //сортируем все банки по убыванию объёма
  while(cans.length && liquid - cans[0] >= 0){
  //пока есть пустая банка и её объём
  //не превышает объём оставшийся краски
    liquid -= cans[0]
    //вычитаем объём банки
    result.push(cans.splice(0,1)[0])
    //выдираем банку из исходного массива
    //и ложим в результирующий
  }
  while ( liquid > 0 ){
  //пока ещё есть краска
    cans = cans.sort((a,b) => Math.abs(liquid-b) - Math.abs(liquid-a))
    //сортируем по принципу:
    //самой последней должна быть банка,
    //объём которой ближе объёму оставшейся краски
    liquid -= cans[cans.length - 1]
    //вычитаем объём банки
    result.push(cans.pop())
    //выдираем банку из исходного массива
    //и ложим в результирующий
  }
  return result
}

let emptyCans = [15,7,10,12,10]
console.log(wrap(33,emptyCans))
//[15, 12, 7] - эти банки использованы
console.log(emptyCans)
//[10,10] - эти остались
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы