LAB #1. Решение задачи о рюкзаке
Задача о рюкзаке — это классическая проблема комбинаторной оптимизации, где требуется выбрать набор предметов с максимальной ценностью при ограничении по весу.
Основные характеристики задачи:
  • Каждый предмет имеет вес и стоимость
  • Предметы нельзя делить на части
  • Можно брать каждый предмет только один раз
  • Цель — максимизировать общую стоимость при соблюдении весового ограничения

Формулировка задачи о рюкзаке

Классическая постановка задачи

Задача о рюкзаке (Knapsack problem) — это одна из классических задач комбинаторной оптимизации. Суть задачи заключается в выборе предметов для помещения в рюкзак с ограниченной вместимостью таким образом, чтобы максимизировать общую ценность выбранных предметов.

Математическая формулировка

Дано:

  • Множество предметов n
  • Для каждого предмета i известны:
    • Вес wi
    • Ценность (стоимость) vi
  • Вместимость рюкзака C

Требуется:

Найти такой набор предметов, который:

  • Не превышает вместимость рюкзака
  • Обеспечивает максимальную суммарную ценность

Формальная запись

Целевая функция:

Максимизировать:

max ∑i=1n vixi

При ограничениях:

  1. Ограничение по вместимости:
    i=1n wixi ≤ C
  2. Ограничения на переменные:
    xi ∈ {0,1}, i = 1,2,...,n

где xi — бинарная переменная:

  • xi = 1, если предмет включен в рюкзак
  • xi = 0, если предмет не включен

Варианты задачи

  • Базовый вариант (0-1 рюкзак): каждый предмет можно взять не более одного раза
  • Неограниченный вариант: предметы можно брать неограниченное количество раз
  • Многомерный рюкзак: учитываются несколько ограничений (вес, объем, стоимость)
  • Фракционный рюкзак: предметы можно разбивать на части

Аналитическое решение

Метод динамического программирования

Наиболее эффективный способ решения задачи о рюкзаке — использование динамического программирования.

Алгоритм решения:

  1. Создание таблицы M[i,j], где:
    • i — номер предмета
    • j — текущий вес рюкзака
  2. Заполнение таблицы по формуле:
    M[i,j] = max(M[i-1,j], vi + M[i-1,j-wi])
  3. Базовые случаи:
    • M[0,j] = 0 для всех j
    • M[i,0] = 0 для всех i

Шаги решения:

  • Инициализация массива M
  • Последовательное заполнение таблицы
  • Восстановление решения из таблицы

Временная сложность:

Алгоритм работает за время O(nC), где:

  • n — количество предметов
  • C — вместимость рюкзака

Пример реализации:

Псевдокод решения:

function knapsack(values, weights, n, C):
    create array M[n+1][C+1]
    
    for i from 0 to n:
        M[i][0] = 0
    
    for j from 0 to C:
        M[0][j] = 0
    
    for i from 1 to n:
        for j from 1 to C:
            if weights[i] <= j:
                M[i][j] = max(M[i-1][j], values[i] + M[i-1][j-weights[i]])
            else:
                M[i][j] = M[i-1][j]
    
    return M[n][C]
        

Особенности применения:

  • Метод эффективен для задач среднего размера
  • Требует большого объема памяти
  • Гарантирует нахождение оптимального решения
Методы решения задачи о рюкзаке

Методы решения задачи о рюкзаке

1. Метод полного перебора

Суть метода

Проверяем все возможные комбинации предметов и выбираем наилучшую.

Пример решения

Даны предметы:

  • Предмет 1: вес = 2 кг, ценность = 30
  • Предмет 2: вес = 3 кг, ценность = 40
  • Предмет 3: вес = 4 кг, ценность = 50
  • Вместимость рюкзака = 6 кг
Шаг 1: Перечисление комбинаций

Комбинации с одним предметом:

  • {1}: вес = 2 кг, ценность = 30
  • {2}: вес = 3 кг, ценность = 40
  • {3}: вес = 4 кг, ценность = 50

Комбинации с двумя предметами:

  • {1,2}: вес = 5 кг, ценность = 70
  • {1,3}: вес = 6 кг, ценность = 80
  • {2,3}: вес = 7 кг (не подходит)

Комбинация с тремя предметами:

  • {1,2,3}: вес = 9 кг (не подходит)
Шаг 2: Выбор оптимального решения

Максимальная ценность = 80 (комбинация {1,3})

2. Жадный алгоритм

Принцип работы

Алгоритм основан на последовательном выборе предметов по убыванию ценности на единицу веса.

Пример решения

Используем те же предметы:

  • Предмет 1: 30/2 = 15 (ценность/кг)
  • Предмет 2: 40/3 ≈ 13.3 (ценность/кг)
  • Предмет 3: 50/4 = 12.5 (ценность/кг)
Шаг 1: Сортировка
  1. Предмет 1 (15)
  2. Предмет 2 (13.3)
  3. Предмет 3 (12.5)
Шаг 2: Добавление в рюкзак
  • Добавляем предмет 1 (вес = 2 кг, осталось места = 4 кг)
  • Добавляем предмет 2 (вес = 3 кг, осталось места = 1 кг)
  • Предмет 3 не помещается (требуется 4 кг)
Результат

Общая ценность = 70
Вес = 5 кг

Важные замечания

Метод перебора

  • Гарантирует нахождение оптимального решения
  • Подходит для малого количества предметов (до 15-20)
  • Сложность растет экспоненциально

Жадный алгоритм

  • Не гарантирует оптимальное решение
  • Работает быстрее метода перебора
  • Эффективен для приближенных решений
Анализ решения задачи о рюкзаке

Анализ решения задачи о рюкзаке

Исходный код

// Входные данные
вес = [2 3 5];    // веса предметов
ценность = [30 40 50];  // ценности предметов
max_вес = 6;     // максимальный вес рюкзака

// Количество предметов
n = length(вес);

// Перебираем все возможные комбинации
for i = 0:(2^n - 1)
    // Преобразуем число в двоичный код
    bin = string(dec2bin(i, n));
    
    // Вычисляем вес и ценность текущей комбинации
    текущий_вес = 0;
    текущая_ценность = 0;
    
    // Исправленный цикл по символам строки
    for j = 1:length(bin)
        if part(bin, j) == '1' then
            текущий_вес = текущий_вес + вес(j);
            текущая_ценность = текущая_ценность + ценность(j);
        end
    end
    
    // Проверяем, подходит ли комбинация
    if текущий_вес <= max_вес then
        // Выводим результат
        disp("Комбинация: " + bin);
        disp("Вес: " + string(текущий_вес));
        disp("Ценность: " + string(текущая_ценность));
        disp("------------------------");
    end
end
                
html

Результаты выполнения

Все возможные комбинации

Комбинация Вес Ценность Допустимость
000 0 0 Допустима
001 5 50 Допустима
010 3 40 Допустима
011 8 90 Недопустима
100 2 30 Допустима
101 7 80 Недопустима
110 5 70 Допустима
111 10 120 Недопустима

Оптимальное решение

Лучшая комбинация: 110

Максимальная ценность: 70

Общий вес: 5 кг

Объяснение результата

Комбинация 110 означает, что мы берем:

  • Первый предмет (вес 2 кг, ценность 30)
  • Второй предмет (вес 3 кг, ценность 40)
  • Третий предмет не берем

Оптимизированный код с выводом лучшей кобинации

// Входные данные
вес = 2 3 5; // веса предметов
ценность = 30 40 50; // ценности предметов
max_вес = 6; // максимальный вес рюкзака

// Количество предметов
n = length(вес);

// Переменные для поиска максимума
max_ценность = 0;
лучшая_комбинация = "";

// Перебираем все возможные комбинации
for i = 0:(2^n - 1)
    // Преобразуем число в двоичный код
    bin = string(dec2bin(i, n));
    
    // Вычисляем вес и ценность текущей комбинации
    текущий_вес = 0;
    текущая_ценность = 0;
    
    // Цикл по символам строки
    for j = 1:length(bin)
        if part(bin, j) == '1' then
            текущий_вес = текущий_вес + вес(j);
            текущая_ценность = текущая_ценность + ценность(j);
        end
    end
    
    // Проверяем, подходит ли комбинация
    if текущий_вес <= max_вес then
        // Обновляем максимум
        if текущая_ценность > max_ценность then
            max_ценность = текущая_ценность;
            лучшая_комбинация = bin;
        end
    end
end

// Выводим результат
disp("Лучшая комбинация: " + лучшая_комбинация);
disp("Максимальная ценность: " + string(max_ценность));
        

Преимущества оптимизированного кода

  • Автоматическое нахождение лучшего решения
  • Отсутствие необходимости просматривать все комбинации
  • Мгновенный вывод оптимального результата

Как работает оптимизация

Код сохраняет только лучшую найденную комбинацию, сравнивая каждую новую допустимую комбинацию с текущей максимальной ценностью.

Заключение

Метод полного перебора позволяет найти оптимальное решение задачи о рюкзаке путем проверки всех возможных комбинаций. Оптимизированный код делает этот процесс более эффективным, автоматически находя наилучшее решение.

Задание
  • 10 класс
    описание:
    • Решить задачу методом перебора вариантов аналитически. "Руками" (07.10)
    • Решить задачу жадным алгоритмом аналитически. "Руками" (14.10)

Данные для решения аналитически 10 КЛАСС

Вариант Тип транспорта Вместимость Груз 1 Груз 2 Груз 3 Груз 4
1 Грузовой автомобиль 3500 кг 800 кг (15000 руб) 1200 кг (20000 руб) 650 кг (12000 руб) 950 кг (18000 руб)
2 Железнодорожный вагон 65 т 15 т (450000 руб) 22 т (600000 руб) 18 т (540000 руб) 12 т (360000 руб)
3 Морской контейнер 28 т 7.5 т (225000 руб) 9.2 т (276000 руб) 6.8 т (204000 руб) 4.5 т (135000 руб)
4 Небольшой грузовик 1200 кг 300 кг (9000 руб) 450 кг (13500 руб) 280 кг (8400 руб) 320 кг (9600 руб)
5 Самолет 85 т 25 т (750000 руб) 32 т (960000 руб) 18 т (540000 руб) 20 т (600000 руб)
6 Речная баржа 150 т 45 т (1350000 руб) 55 т (1650000 руб) 30 т (900000 руб) 20 т (600000 руб)
7 Городской фургон 800 кг 200 кг (6000 руб) 250 кг (7500 руб) 180 кг (5400 руб) 220 кг (6600 руб)
8 Автоконтейнер 22 т 6.5 т (195000 руб) 7.2 т (216000 руб) 5.8 т (174000 руб) 2.5 т (75000 руб)
9 Железнодорожный контейнер 45 т 12 т (360000 руб) 15 т (450000 руб) 10 т (300000 руб) 8 т (240000 руб)
10 Морской сухогруз 5000 т 1500 т (4500000 руб) 1800 т (5400000 руб) 1200 т (3600000 руб) 500 т (1500000 руб)

Примечания к данным:

  • Все веса указаны в метрической системе
  • Ценности указаны в российских рублях
  • Данные можно использовать для:
    • Аналитического решения
    • Тестирования алгоритмов
    • Обучающих примеров

Made on
Tilda