Задача о ранце - это хорошо известная задача комбинаторной оптимизации. Учитывая набор элементов, каждый из которых имеет вес и значение, мы должны определить количество каждого элемента для включения в коллекцию, чтобы общий вес был меньше или равен заданному пределу, а общее значение должно быть максимальным.
Название проблемы происходит от проблемы, с которой сталкивается тот, кто ограничен рюкзаком фиксированного размера и должен вместить в него самые ценные предметы.
В этом руководстве вы собираетесь решить проблему с рюкзаком в Java в Eclipse, следуя подходу динамического программирования.
Обратите внимание, что вы также можете посмотреть это руководство в видео на YouTube:
Разработка предмета
Во-первых, мы начнем с разработки предмета для задачи о рюкзаке. Элемент будет иметь следующие свойства:
- имя помогает нам идентифицировать его
- вес, представляющий вес предмета.
- value, представляющий ценность элемента
Мы также добавляем метод str, возвращающий String представление Item. Это дает нам следующий код:
Представление решения
Как только проблема с рюкзаком будет решена, нам понадобится класс, представляющий решение. Мы сохраним максимальное значение, которое мы можем достичь, а также предметы, которые нужно включить в сумку, чтобы максимизировать ценность.
Итак, объект Solution будет иметь следующие свойства:
- значение, хранящее максимальное значение, которое мы можем достичь
- Список items ’, в котором хранятся объекты Item, которые нужно положить в сумку, чтобы получить максимальную ценность и решить проблему с рюкзаком.
Мы также добавляем метод display для вывода решения на экран. Это дает нам следующий код:
Решение проблемы с рюкзаком
Чтобы решить задачу о ранце, мы собираемся реализовать алгоритм динамического программирования. Подобно представленному в Википедии, этот алгоритм можно представить в виде псевдокода:
// Input: 2 // Values (stored in array v) 3 // Weights (stored in array w) 4 // Number of distinct items (n) 5 // Knapsack capacity (W) 6 // NOTE: The array "v" and array "w" are assumed to store all relevant values starting at index 1. 7 8 for j from 0 to W do: 9 m[0, j] := 0 10 11 for i from 1 to n do: 12 for j from 0 to W do: 13 if w[i] > j then: 14 m[i, j] := m[i-1, j] 15 else: 16 m[i, j] := max(m[i-1, j], m[i-1, j-w[i]] + v[i])
Таким образом, в матрице m значение m [i, w] будет максимальным значением, которое может быть достигнуто с весом, меньшим или равным w, с использованием элементов до i (первых i элементов).
Он дает нам следующий код Java для реализации этого алгоритма:
В конце нашего алгоритма динамического программирования максимальное значение можно найти в матрице в ячейке matrix [NB_ITEMS] [capacity].
Поиск предметов, которые нужно положить в сумку
Следующий шаг - найти предметы, которые нужно положить в сумку, чтобы получить максимальную ценность. Либо результат получается из ячейки верхней матрицы [i-1] [capacity], либо из значений [i-1] + weights [i-1] [capacity-weights [i-1]], как в матрице, построенной ранее.
Если он идет последним, это означает, что предмет включен в сумку, чтобы максимизировать ценность. Он дает нам следующий код, чтобы найти элементы, которые нужно включить:
Сборка всех деталей
В конце метода resolve мы возвращаем объект Solution, содержащий максимальное значение value и список items ' включить в сумку. Мы также добавляем метод display в объект Knapsack для вывода на экран исходной задачи о рюкзаке.
Наконец, мы добавляем основную точку входа и собираем все части для создания задачи о ранце, отображаем ее на экране, решаем и затем отображаем решение.
Это дает нам следующий код для класса Knapsack:
Наш решатель в действии
Последний шаг - запустить наш инструмент для решения проблем с рюкзаком. Рассмотрим следующий пример задачи о ранце:
- Сумка вместимостью 15кг.
- 5 предметов на выбор с определенными значениями и весом
Мы запускаем наш решатель задач с рюкзаком с этим экземпляром. По окончании выполнения решение отображается в консоли:
Таким образом, значение увеличивается до 15 за счет включения элементов 2, 3, 4 и 5 в сумку.
Вот и все для этого урока!
Чтобы найти больше руководств по разработке на Java, вы можете подписаться на канал SSaurel:
Если вы хотите открыть для себя несколько книг по программированию на Java, я советую вам прочитать следующую статью с моей подборкой из 6 лучших книг по программированию на Java: