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_ценность));
        

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

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

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

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

Заключение

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

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

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

Вариант Тип транспорта Вместимость Груз 1 Груз 2 Груз 3 Груз 4 Груз 5 Груз 6
1 Автовоз 5000 кг 1000 кг (25000 руб) 1300 кг (32500 руб) 800 кг (20000 руб) 900 кг (22500 руб) 700 кг (17500 руб) 300 кг (7500 руб)
2 Платформа для негабаритных грузов 90 т 20 т (600000 руб) 28 т (840000 руб) 18 т (540000 руб) 15 т (450000 руб) 8 т (240000 руб) 11 т (330000 руб)
3 Рефрижератор 30 т 7.5 т (225000 руб) 8.5 т (255000 руб) 6.2 т (186000 руб) 5.3 т (159000 руб) 2.5 т (75000 руб) 3.5 т (105000 руб)
4 Микроавтобус 1000 кг 250 кг (5000 руб) 300 кг (6000 руб) 200 кг (4000 руб) 150 кг (3000 руб) 100 кг (2000 руб) 50 кг (1000 руб)
5 Грузовой вертолет 65 т 25 т (750000 руб) 22 т (660000 руб) 18 т (540000 руб) 10 т (300000 руб) 6 т (180000 руб) 4 т (120000 руб)
6 Сухогруз 2500 т 600 т (1800000 руб) 550 т (1650000 руб) 450 т (1350000 руб) 350 т (1050000 руб) 300 т (900000 руб) 250 т (750000 руб)
7 Изотермический вагон 55 т 12 т (360000 руб) 15 т (450000 руб) 10 т (300000 руб) 8 т (240000 руб) 7 т (210000 руб) 3 т (90000 руб)
8 Контейнеровоз 40 т 10 т (300000 руб) 9 т (270000 руб) 8 т (240000 руб) 7 т (210000 руб) 4 т (120000 руб) 2 т (60000 руб)
9 Трамвай грузовой 1500 кг 350 кг (7000 руб) 400 кг (8000 руб) 300 кг (6000 руб) 250 кг (5000 руб) 150 кг (3000 руб) 50 кг (1000 руб)
10 Мультимодальный модуль 28 т 8 т (240000 руб) 7.5 т (225000 руб) 6 т (180000 руб) 5 т (150000 руб) 1 т (30000 руб) 0.5 т (15000 руб)

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

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

Made on
Tilda