<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=94.25.228.117&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=94.25.228.117&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/94.25.228.117"/>
		<updated>2026-06-11T18:40:57Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D1%80%D1%8E%D0%BA%D0%B7%D0%B0%D0%BA%D0%B5&amp;diff=57104</id>
		<title>Задача о рюкзаке</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D1%80%D1%8E%D0%BA%D0%B7%D0%B0%D0%BA%D0%B5&amp;diff=57104"/>
				<updated>2016-12-07T14:32:26Z</updated>
		
		<summary type="html">&lt;p&gt;94.25.228.117: /* Варианты решения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Задача о рюкзаке'''(''англ. Knapsack problem'') — дано &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; предметов, &amp;lt;tex&amp;gt;n_i&amp;lt;/tex&amp;gt; предмет имеет массу &amp;lt;tex&amp;gt; w_i &amp;gt; 0&amp;lt;/tex&amp;gt; и стоимость &amp;lt;tex&amp;gt; p_i &amp;gt; 0&amp;lt;/tex&amp;gt;. Необходимо выбрать из этих предметов такой набор, чтобы суммарная масса не превосходила заданной величины &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; (вместимость рюкзака), а суммарная стоимость была максимальна.&lt;br /&gt;
&lt;br /&gt;
== Формулировка задачи ==&lt;br /&gt;
&lt;br /&gt;
Дано &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; предметов, &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt; - вместимость рюкзака, &amp;lt;tex&amp;gt;w=\{w_{1},w_{2},...,w_{N}\}&amp;lt;/tex&amp;gt; — соответствующий ему набор положительных целых весов, &amp;lt;tex&amp;gt;p=\{p_{1},p_{2},...,p_{N}\}&amp;lt;/tex&amp;gt; — соответствующий ему набор положительных целых стоимостей. Нужно найти набор бинарных величин &amp;lt;tex&amp;gt;B=\{b_{1},b_{2},...,b_{N}\}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b_{i} = 1 &amp;lt;/tex&amp;gt;, если предмет &amp;lt;tex&amp;gt;n_i&amp;lt;/tex&amp;gt; включен в набор, &amp;lt;tex&amp;gt; b_{i} = 0 &amp;lt;/tex&amp;gt;, если предмет &amp;lt;tex&amp;gt;n_i&amp;lt;/tex&amp;gt; не включен, и такой что:&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;tex&amp;gt;b_{1} w_{1}+ ... + b_{N} w_{N} \le W&amp;lt;/tex&amp;gt;&lt;br /&gt;
#&amp;lt;tex&amp;gt;b_{1} p_{1}+ ... + b_{N} p_{N} &amp;lt;/tex&amp;gt; максимальна.&lt;br /&gt;
&lt;br /&gt;
== Варианты решения ==&lt;br /&gt;
&lt;br /&gt;
Задачу о рюкзаке можно решить несколькими способами:&lt;br /&gt;
&lt;br /&gt;
* Перебирать все подмножества набора из N предметов. Сложность такого решения &amp;lt;tex&amp;gt;O({2^{N}})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Методом [[Meet-in-the-middle|Meet-in-the-middle]]. Сложность решения &amp;lt;tex&amp;gt; O({2^{N/2}}\times{N}) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Метод динамического программирования. Сложность — &amp;lt;tex&amp;gt;O(N \times W)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Метод динамического программирования ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;A(k, s)&amp;lt;/tex&amp;gt; есть максимальная стоимости предметов, которые можно уложить в рюкзак вместимости &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;, если можно использовать только первые &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; предметов, то есть &amp;lt;tex&amp;gt;\{n_1,n_2,...,n_k\}&amp;lt;/tex&amp;gt;, назовем этот набор допустимых предметов для &amp;lt;tex&amp;gt;A(k,s)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(k, 0) = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;A(0, s) = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Найдем &amp;lt;tex&amp;gt;A(k, s)&amp;lt;/tex&amp;gt;. Возможны 2 варианта:&lt;br /&gt;
&lt;br /&gt;
#Если предмет &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; не попал в рюкзак. Тогда &amp;lt;tex&amp;gt;A(k, s)&amp;lt;/tex&amp;gt; равно максимальной стоимости рюкзака с такой же вместимостью и набором допустимых предметов &amp;lt;tex&amp;gt;\{n_1,n_2,...,n_{k-1}\}&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;A(k,s) = A(k-1, s)&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Если &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; попал в рюкзак. Тогда &amp;lt;tex&amp;gt;A(k, s)&amp;lt;/tex&amp;gt; равно максимальной стоимости рюкзака, где вес &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; уменьшаем на вес &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; -ого предмета и набор допустимых предметов &amp;lt;tex&amp;gt;\{n_1,n_2,...,n_{k-1}\}&amp;lt;/tex&amp;gt; плюс стоимость &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;A(k-1, s-w_k) + p_k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
То есть: &lt;br /&gt;
&amp;lt;tex&amp;gt;A(k,s) = max(A(k-1,s), A(k-1,s-w_{k}) + p_{k})&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Стоимость искомого набора равна &amp;lt;tex&amp;gt;A(N,W)&amp;lt;/tex&amp;gt;, так как нужно найти максимальную стоимость рюкзака, где все предметы допустимы и вместимость рюкзака &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Восстановим набор предметов, входящих в рюкзак'''&lt;br /&gt;
&lt;br /&gt;
Будем определять, входит ли &amp;lt;tex&amp;gt;n_i&amp;lt;/tex&amp;gt; предмет в искомый набор. Начинаем с элемента &amp;lt;tex&amp;gt;A(i,w)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;i = N&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;w = W&amp;lt;/tex&amp;gt;. Для этого сравниваем &amp;lt;tex&amp;gt;A(i,w)&amp;lt;/tex&amp;gt; со следующими значениями:&lt;br /&gt;
&lt;br /&gt;
#Максимальная стоимость рюкзака с такой же вместимостью и набором допустимых предметов &amp;lt;tex&amp;gt;\{n_1,n_2,...,n_{i-1}\}&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;A(i-1, w)&amp;lt;/tex&amp;gt;&lt;br /&gt;
#Максимальная стоимость рюкзака с вместимостью на &amp;lt;tex&amp;gt;w_i&amp;lt;/tex&amp;gt; меньше и набором допустимых предметов &amp;lt;tex&amp;gt;\{n_1,n_2,...,n_{i-1}\}&amp;lt;/tex&amp;gt; плюс стоимость &amp;lt;tex&amp;gt;p_i&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;A(i-1, w-w_i)+p_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Заметим, что при построении &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; мы выбирали максимум из этих значений и записывали в &amp;lt;tex&amp;gt;A(i, w)&amp;lt;/tex&amp;gt;. Тогда будем сравнивать &amp;lt;tex&amp;gt;A(i, w)&amp;lt;/tex&amp;gt; c &amp;lt;tex&amp;gt;A(i-1, w)&amp;lt;/tex&amp;gt;, если равны, тогда &amp;lt;tex&amp;gt;n_i&amp;lt;/tex&amp;gt; не входит в искомый набор, иначе входит.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
Сначала генерируем &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
 for i = 0..W&lt;br /&gt;
   A[0][i] = 0;&lt;br /&gt;
 for i = 0..N&lt;br /&gt;
   A[i][0] = 0;   //Первые элементы приравниваем к 0&lt;br /&gt;
 for k = 1..N               &lt;br /&gt;
   for s = 1..W   //Перебираем для каждого k все вместимости &lt;br /&gt;
     if s &amp;gt;= w[k]    //Если текущий предмет вмещается в рюкзак&lt;br /&gt;
       A[k][s] = max(A[k-1][s], A[k-1][s-w[k]]+p[k]); //выбираем класть его или нет&lt;br /&gt;
     else &lt;br /&gt;
       A[k][s] = A[k-1][s];             //иначе, не кладем&lt;br /&gt;
&lt;br /&gt;
Затем найдем набор &amp;lt;tex&amp;gt;ans&amp;lt;/tex&amp;gt; предметов, входящих в рюкзак, рекурсивной функцией:&lt;br /&gt;
&lt;br /&gt;
 findAns(k, s)&lt;br /&gt;
   if A[k][s] == 0 &lt;br /&gt;
     return;&lt;br /&gt;
   if A[k-1][s] == A[k][s]&lt;br /&gt;
     findAns(k-1, s);&lt;br /&gt;
   else &lt;br /&gt;
     findAns(k-1, s - w[k]);&lt;br /&gt;
     ans.push(k);&lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма &amp;lt;tex&amp;gt;O(N \times W)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Пример ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;W = 13, N = 5&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;w_{1} = 3, p_{1} = 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;w_{2} = 4, p_{2} = 6 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;w_{3} = 5, p_{3} = 4 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;w_{4} = 8, p_{4} = 7 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;w_{5} = 9, p_{5} = 6 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Knapsack problem0.png]]&lt;br /&gt;
&lt;br /&gt;
Числа от 0 до 13 в первой строчке обозначают вместимость рюкзака.&lt;br /&gt;
&lt;br /&gt;
В первой строке как только вместимость рюкзака &amp;lt;tex&amp;gt;n \ge 3&amp;lt;/tex&amp;gt;, добавляем в рюкзак 1 предмет.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;lt;tex&amp;gt;k = 3&amp;lt;/tex&amp;gt;, при каждом &amp;lt;tex&amp;gt;s \ge 5 (&amp;lt;/tex&amp;gt;так как &amp;lt;tex&amp;gt;w_3 = 5)&amp;lt;/tex&amp;gt; сравниваем &amp;lt;tex&amp;gt;A[k-1][s]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;A[k-1][s-w_3]+p_3&amp;lt;/tex&amp;gt; и записываем в &amp;lt;tex&amp;gt;A[k][s]&amp;lt;/tex&amp;gt; стоимость либо рюкзака без третьего предмета, но с таким же весом, либо с третьим предметом, тогда стоимость равна стоимости третьего предмета плюс стоимость рюкзака с вместимостью на &amp;lt;tex&amp;gt;w_3&amp;lt;/tex&amp;gt; меньше.     &lt;br /&gt;
&lt;br /&gt;
Максимальная стоимость рюкзака находится в &amp;lt;tex&amp;gt;A(5, 13)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Восстановление набора предметов, из которых состоит максимально дорогой рюкзак.'''&lt;br /&gt;
&lt;br /&gt;
Начиная с &amp;lt;tex&amp;gt;A(5, 13)&amp;lt;/tex&amp;gt; восстанавливаем ответ.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Задача о рюкзаке3.png]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, в набор входит &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; предмет.&lt;br /&gt;
&lt;br /&gt;
Стоимость рюкзака &amp;lt;tex&amp;gt;= 6 + 7 = 13&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вес рюкзака &amp;lt;tex&amp;gt;= 4 + 8 = 12&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Другие задачи семейства=&lt;br /&gt;
==Ограниченный рюкзак ==&lt;br /&gt;
'''Ограниченный рюкзак''' (англ. ''Bounded Knapsack Problem'') - обобщение классической задачи, когда любой предмет может быть взят некоторое количество раз.&lt;br /&gt;
&lt;br /&gt;
'''Пример:''' Вор грабит склад. Он может унести ограниченный вес, каждый товар на складе содержится в определенном ограниченном количестве. Нужно унести предметов на максимальную сумму.&lt;br /&gt;
===Формулировка Задачи===&lt;br /&gt;
Каждый предмет может быть выбран ограниченное &amp;lt;tex&amp;gt;b_i&amp;lt;/tex&amp;gt; число раз.&lt;br /&gt;
Задача выбрать число &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; предметов каждого типа так, чтобы&lt;br /&gt;
&lt;br /&gt;
* максимизировать общую стоимость: &amp;lt;tex&amp;gt;\sum_{i=1}^N p_ix_i&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* выполнялось условие совместности: &amp;lt;tex&amp;gt;\sum_{i=1}^N w_ix_i \le W&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;tex&amp;gt; x_i \in (0,1,...,b_i)&amp;lt;/tex&amp;gt; для всех &amp;lt;tex&amp;gt; i= 1,2,...,N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Варианты решения===&lt;br /&gt;
При небольших &amp;lt;tex&amp;gt;b_i&amp;lt;/tex&amp;gt; решается сведением к классической задаче о рюкзаке. В иных случаях:&lt;br /&gt;
* Методом ветвей и границ.&lt;br /&gt;
* Методом динамического программирования.&lt;br /&gt;
&lt;br /&gt;
===Метод динамического программирования===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;d(i,c)&amp;lt;/tex&amp;gt; максимальная стоимость любого возможного числа предметов типов от 1 до &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, суммарным весом до &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Заполним &amp;lt;tex&amp;gt;d(0,c)&amp;lt;/tex&amp;gt; нулями.&lt;br /&gt;
&lt;br /&gt;
Тогда меняя i от 1 до &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, рассчитаем на каждом шаге &amp;lt;tex&amp;gt;d(i,c)&amp;lt;/tex&amp;gt;, для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; от 1 до &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt;, по рекуррентной формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;d(i,c) = max(d(i - 1, c - lw_i) + lp_i) &amp;lt;/tex&amp;gt; по всем целым &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; из промежутка &amp;lt;tex&amp;gt; 0 \le l \le min(b_i,\lfloor c/w_i \rfloor)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Если не нужно восстанавливать ответ, то можно использовать одномерный массив &amp;lt;tex&amp;gt;d(c)&amp;lt;/tex&amp;gt; вместо двумерного.&lt;br /&gt;
&lt;br /&gt;
После выполнения в &amp;lt;tex&amp;gt; d(N,W) &amp;lt;/tex&amp;gt; будет лежать максимальная стоимость предметов, помещающихся в рюкзак.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 for i = 0..W // база&lt;br /&gt;
   d[0][i] = 0;&lt;br /&gt;
 for i = 1..N             &lt;br /&gt;
   for c = 1..W   //Перебираем для каждого i, все вместимости &lt;br /&gt;
     d[i][c] = d[i - 1][c];&lt;br /&gt;
     for l = min(b[i], c / w[i]) .. 1 // ищем l для которого выполняется максимум&lt;br /&gt;
         d[i][c] =  max(d[i][c], d[i - 1][c - l * w[i]] + p[i] * l);&lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма &amp;lt;tex&amp;gt;O(NW^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Неограниченный рюкзак==&lt;br /&gt;
'''Неограниченный рюкзак''' (англ.''Unbounded Knapsack Problem'') - обобщение ограниченного рюкзака, в котором любой предмет может быть выбран любое количество раз.&lt;br /&gt;
&lt;br /&gt;
'''Пример:''' Перекупщик закупается на оптовой базе. Он может увезти ограниченное количество товара, количество товара каждого типа на базе не ограниченно. Нужно увезти товар на максимальную сумму.&lt;br /&gt;
===Формулировка Задачи===&lt;br /&gt;
Каждый предмет может быть выбран любое число раз.&lt;br /&gt;
Задача выбрать количество &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; предметов каждого типа так, чтобы&lt;br /&gt;
&lt;br /&gt;
*максимизировать общую стоимость: &amp;lt;tex&amp;gt;\sum_{i=1}^N p_ix_i&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
*выполнялось условие совместности: &amp;lt;tex&amp;gt;\sum_{i=1}^N w_ix_i \le W&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;tex&amp;gt; x_i \ge 0 &amp;lt;/tex&amp;gt; целое,  для всех &amp;lt;tex&amp;gt; i= 1,2,...,N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Варианты решения===&lt;br /&gt;
Самые распространенные методы точного решения это:&lt;br /&gt;
* Метод ветвей и границ.&lt;br /&gt;
* Метод динамического программирования.&lt;br /&gt;
&lt;br /&gt;
===Метод динамического программирования===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;d(i,c)&amp;lt;/tex&amp;gt; максимальная стоимость любого количества вещей типов от 1 до &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, суммарным весом до &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; включительно.&lt;br /&gt;
&lt;br /&gt;
Заполним &amp;lt;tex&amp;gt;d(0,c)&amp;lt;/tex&amp;gt; нулями.&lt;br /&gt;
&lt;br /&gt;
Тогда меняя i от 1 до &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, рассчитаем на каждом шаге &amp;lt;tex&amp;gt;d(i,c)&amp;lt;/tex&amp;gt;, для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; от 0 до &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt;, по рекуррентной формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
d(i,c) =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 d(i - 1, c) &amp;amp; for\ c = 0, ..., w_i - 1; \\&lt;br /&gt;
 max(d(i - 1, c), d(i, c - w_i) + p_i) &amp;amp; for\ c = w_i, ..., W; &lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После выполнения в &amp;lt;tex&amp;gt; d(N,W) &amp;lt;/tex&amp;gt; будет лежать максимальная стоимость предметов, помещающихся в рюкзак.&lt;br /&gt;
&lt;br /&gt;
Если не нужно восстанавливать ответ, то можно использовать одномерный массив &amp;lt;tex&amp;gt;d(c)&amp;lt;/tex&amp;gt; вместо двумерного и использовать формулу:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;  d(c) = max(d(c), d(c - w_i) + p_i)   &amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма &amp;lt;tex&amp;gt;O(NW)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Непрерывный рюкзак==&lt;br /&gt;
'''Непрерывный рюкзак''' (англ. ''Continuous knapsack problem'') - вариант задачи, в котором возможно брать любою дробную часть от предмета, при этом удельная стоимость сохраняется.&lt;br /&gt;
&lt;br /&gt;
'''Пример:''' Вор грабит мясника. Суммарно он может унести ограниченный вес товаров. Вор может резать товары без ущерба к удельной стоимости. Нужно унести товара на максимальную сумму.&lt;br /&gt;
===Формулировка Задачи===&lt;br /&gt;
Задача выбрать часть &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; каждого предмета так, чтобы&lt;br /&gt;
&lt;br /&gt;
*максимизировать общую стоимость: &amp;lt;tex&amp;gt;\sum_{i=1}^N p_ix_i&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
*выполнялось условие совместности: &amp;lt;tex&amp;gt;\sum_{i=1}^N w_ix_i \le W&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;tex&amp;gt; 0 \le x_i \le 1&amp;lt;/tex&amp;gt; дробное, для всех &amp;lt;tex&amp;gt; i= 1,2,...,N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Варианты решения===&lt;br /&gt;
Возможность брать любую часть от предмета сильно упрощает задачу. Жадный алгоритм дает оптимальное решение в данном случае.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
 sort(); // сортируем в порядке убывания удельной стоимости.&lt;br /&gt;
 for i = 1..N // идем по предметам            &lt;br /&gt;
       if W &amp;gt;= w[i]    //если помещается - берем&lt;br /&gt;
        sum += p[i];&lt;br /&gt;
        W -= w[i];&lt;br /&gt;
    else&lt;br /&gt;
        sum += W / w[i] * p[i];// иначе берем сколько можно и выходим&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
==Задача о суммах подмножеств==&lt;br /&gt;
'''Задача о суммах подмножеств''' (англ. ''Subset-sum problem, Value Independent Knapsack Problem'') - задача из семейства, в которой стоимость предмета совпадает с его весом.&lt;br /&gt;
&lt;br /&gt;
'''Пример:''' Машина может увезти определенное количество груза. Нужно увезти как можно больше крупного неделимого мусора за раз.&lt;br /&gt;
===Формулировка Задачи===&lt;br /&gt;
Нужно выбрать подмножество так, чтобы сумма ближе всего к &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt;, но не превысила его. Формально, нужно найти набор бинарных величин &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt;, так чтобы&lt;br /&gt;
&lt;br /&gt;
*максимизировать общую стоимость: &amp;lt;tex&amp;gt;\sum_{i=1}^N w_ix_i&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
*выполнялось условие совместности: &amp;lt;tex&amp;gt;\sum_{i=1}^N w_ix_i \le W&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; x_j = 1 &amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt; j&amp;lt;/tex&amp;gt; предмет назначен рюкзаку, иначе &amp;lt;tex&amp;gt; x_{ij} = 0 &amp;lt;/tex&amp;gt;,  для всех &amp;lt;tex&amp;gt; i= 1,2,...,N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Варианты решения===&lt;br /&gt;
Для решения пригодны любые методы применяемые для классической задачи, однако специализированые алгоритмы обычно более оптимальны по параметрам. Используются:&lt;br /&gt;
* Метод динамического программирования.&lt;br /&gt;
* Гибридный метод на основе динамического программирования и поиска по дереву. В худшем случае, работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Метод динамического программирования===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;d(i,c)&amp;lt;/tex&amp;gt; максимальная сумма  &amp;lt;tex&amp;gt;\le c&amp;lt;/tex&amp;gt;, подмножества взятого из &amp;lt;tex&amp;gt; 1, ...,\ i&amp;lt;/tex&amp;gt; элементов.&lt;br /&gt;
&lt;br /&gt;
Заполним &amp;lt;tex&amp;gt;d(0,c)&amp;lt;/tex&amp;gt; нулями.&lt;br /&gt;
&lt;br /&gt;
Тогда меняя i от 1 до &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, рассчитаем на каждом шаге &amp;lt;tex&amp;gt;d(i,c)&amp;lt;/tex&amp;gt;, для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; от 0 до &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt;, по рекуррентной формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
d(i,c) =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 d(i - 1, c) &amp;amp; for\ c = 0, ..., w_i - 1; \\&lt;br /&gt;
 max(d(i - 1, c), d(i - 1, c - w_i) + w_i) &amp;amp; for\ c = w_i, ..., W; &lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После выполнения в &amp;lt;tex&amp;gt; d(N,W) &amp;lt;/tex&amp;gt; будет лежать максимальная сумма подмножества, не превышающая заданное значение.&lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма &amp;lt;tex&amp;gt;O(NW)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Задача о размене==&lt;br /&gt;
'''Задача о размене''' (англ. ''Change-Making problem'') - имеются &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; неисчерпаемых типов предметов с весами &amp;lt;tex&amp;gt;w_i&amp;lt;/tex&amp;gt;.  Нужно наполнить рюкзак предметами с суммарным весом &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Часто задачу ставят как, дать сдачу наименьшим количеством монет.&lt;br /&gt;
===Формулировка Задачи===&lt;br /&gt;
Каждый предмет может быть выбран любое число раз.&lt;br /&gt;
Задача выбрать количество &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; предметов каждого типа так, чтобы&lt;br /&gt;
&lt;br /&gt;
*минимизировать количество взятых предметов: &amp;lt;tex&amp;gt;\sum_{i=1}^N x_i&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
*сумма весов выбранных предметов равнялась вместимости рюкзака: &amp;lt;tex&amp;gt;\sum_{i=1}^N w_ix_i = W&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Где &amp;lt;tex&amp;gt; x_i \ge 0 &amp;lt;/tex&amp;gt; целое,  для всех &amp;lt;tex&amp;gt; i= 1,2,...,N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
===Варианты решения===&lt;br /&gt;
Самые распространенные методы точного решения это:&lt;br /&gt;
* Метод ветвей и границ.&lt;br /&gt;
* Метод динамического программирования.&lt;br /&gt;
&lt;br /&gt;
===Метод динамического программирования===&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;d(i,c)&amp;lt;/tex&amp;gt; минимальное число предметов, типов от 1 до &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, необходимое, чтобы заполнить рюкзак вместимостью &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;d(0,0) = 0&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;d(0,c) = \inf&amp;lt;/tex&amp;gt; для всех &amp;lt;tex&amp;gt;c &amp;gt; 0&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Тогда меняя i от 1 до &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;, рассчитаем на каждом шаге &amp;lt;tex&amp;gt;d(i,c)&amp;lt;/tex&amp;gt;, для &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; от 0 до &amp;lt;tex&amp;gt;W&amp;lt;/tex&amp;gt;, по рекуррентной формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
d(i,c) =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
 d(i - 1, c) &amp;amp; for\ c = 0, ..., w_i - 1; \\&lt;br /&gt;
 min(d(i - 1, c), d(i, c - w_i) + 1) &amp;amp; for\ c = w_i, ..., W; &lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После выполнения в &amp;lt;tex&amp;gt; d(N,W) &amp;lt;/tex&amp;gt; будет лежать максимальная стоимость предметов, помещающихся в рюкзак.&lt;br /&gt;
&lt;br /&gt;
Если не нужно восстанавливать ответ, то можно использовать одномерный массив &amp;lt;tex&amp;gt;d(c)&amp;lt;/tex&amp;gt; вместо двумерного и использовать формулу:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;  d(c) = min(d(c), d(c - w_i) + 1) \qquad  for\ c = w_i, ..., W&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма &amp;lt;tex&amp;gt;O(NW)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Задача об упаковке==&lt;br /&gt;
'''Задача об упаковке''' (англ. ''Bin Packing Problem'') - имеются &amp;lt;tex&amp;gt; N &amp;lt;/tex&amp;gt; рюкзаков вместимости &amp;lt;tex&amp;gt; W &amp;lt;/tex&amp;gt; и столько же предметов с весами &amp;lt;tex&amp;gt;w_i&amp;lt;/tex&amp;gt;. Нужно распределить все предметы, задействовав минимальное количество рюкзаков.&lt;br /&gt;
&lt;br /&gt;
'''Пример:''' Нужно вывезти из шахты все куски руды, используя наименьшее число вагонеток.&lt;br /&gt;
===Формулировка Задачи===&lt;br /&gt;
Математически задачу можно представить так:&lt;br /&gt;
&lt;br /&gt;
*минимизировать количество рюкзаков: &amp;lt;tex&amp;gt;\sum_{i=1}^N y_i&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
*так чтобы выполнялось условие на совместность: &amp;lt;tex&amp;gt;\sum_{i=1}^N w_ix_{ij} \le Wy_j \qquad j \in {1, ..., N}&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; x_{ij} = 1 &amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt; j&amp;lt;/tex&amp;gt; предмет назначен  &amp;lt;tex&amp;gt;i &amp;lt;/tex&amp;gt; рюкзаку. Иначе &amp;lt;tex&amp;gt; x_{ij} = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; y_i = 1 &amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt; i&amp;lt;/tex&amp;gt; рюкзак используется. Иначе &amp;lt;tex&amp;gt; y_i = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Варианты решения===&lt;br /&gt;
Применение динамического программирования нецелесообразно. Обычно применяют аппроксимационные алгоритмы, либо используют метод ветвей и границ.&lt;br /&gt;
&lt;br /&gt;
==Мультипликативный рюкзак==&lt;br /&gt;
'''Мультипликативный рюкзак''' (англ. ''Multiple Knapsack Problem'') - есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; предметов и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; рюкзаков (&amp;lt;tex&amp;gt;M\le N&amp;lt;/tex&amp;gt;). У каждого рюкзака своя вместимость &amp;lt;tex&amp;gt;W_i&amp;lt;/tex&amp;gt;. Задача: выбрать &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; не пересекающихся множеств, назначить соответствие рюкзакам так, чтобы суммарная стоимость была максимальна, а вес предметов в каждом рюкзаке не превышал его вместимость.&lt;br /&gt;
&lt;br /&gt;
'''Пример:''' У транспортной компании есть парк машин разной грузоподъемности. Нужно перевезти товара на максимальную сумму с одного склада на другой единовременно.&lt;br /&gt;
===Формулировка Задачи===&lt;br /&gt;
Максимизировать &amp;lt;tex&amp;gt;\sum_{i=1}^M \sum_{j=1}^{N} p_jx_{ij}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
так, чтобы &amp;lt;tex&amp;gt;\sum_{i=1}^N w_jx_{ij} \le W_i&amp;lt;/tex&amp;gt; выполнялось для всех &amp;lt;tex&amp;gt; i= 1,2,...,N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum_{j=1}^{M}x_{ij}=1&amp;lt;/tex&amp;gt; для всех &amp;lt;tex&amp;gt; i= 1,2,...,N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; x_{ij} = 1 &amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt; j&amp;lt;/tex&amp;gt; предмет назначен  &amp;lt;tex&amp;gt;i &amp;lt;/tex&amp;gt; рюкзаку. Иначе &amp;lt;tex&amp;gt; x_{ij} = 0 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Варианты решения===&lt;br /&gt;
Применение динамического программирования, для задач данного типа нецелесообразно. Используются вариации метода ветвей и границ.&lt;br /&gt;
&lt;br /&gt;
==Задача о назначении==&lt;br /&gt;
'''Задача о назначении''' (англ. ''Generalized Assignment Problem'') - Наиболее общая задача семейства. Отличается от мультипликативного рюкзака тем, что каждый предмет имеет различные характеристики в зависимости от рюкзака, куда его помещают. Есть &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; предметов и &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; рюкзаков (&amp;lt;tex&amp;gt;M\le N&amp;lt;/tex&amp;gt;). У каждого рюкзака своя вместимость &amp;lt;tex&amp;gt;W_i&amp;lt;/tex&amp;gt;, у &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; предмета &amp;lt;tex&amp;gt; p_{ij} &amp;lt;/tex&amp;gt; стоимость и вес, при помещении его в &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; рюкзак, равны &amp;lt;tex&amp;gt; p_{ij} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; w_{ij} &amp;lt;/tex&amp;gt;  соответственно.  Задача: выбрать &amp;lt;tex&amp;gt;M&amp;lt;/tex&amp;gt; не пересекающихся множеств, назначить соответствие рюкзакам так, чтобы суммарная стоимость была максимальна, а вес предметов в каждом рюкзаке не превышал его вместимость.&lt;br /&gt;
Весьма важная задача, так как она моделирует оптимальное распределение различных задач между вычислительными блоками.&lt;br /&gt;
===Формулировка Задачи===&lt;br /&gt;
&lt;br /&gt;
Максимизировать стоимость выбранных предметов &amp;lt;tex&amp;gt;\sum_{i=1}^M\sum_{j=1}^N p_{ij} x_{ij}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
при выполнении условия совместности &amp;lt;tex&amp;gt;\sum_{j=1}^N w_{ij} x_{ij} \le W_i \qquad i=1, \ldots, M&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \sum_{i=1}^M x_{ij} \leq 1 \qquad j=1, \ldots, N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; x_{ij} \in \{0,1\} \qquad i=1, \ldots, N, \quad j=1, \ldots, N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Варианты решения===&lt;br /&gt;
Применение динамического программирования нецелесообразно. Наиболее используем метод ветвей и границ.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
*[http://informatics.mccme.ru/moodle/mod/book/view.php?id=815&amp;amp;chapterid=60 Дистанционная подготовка по информатике]&lt;br /&gt;
*[http://rosettacode.org/wiki/Knapsack_Problem Код для нескольких задач семейства на всевозможных языках]&lt;br /&gt;
*[http://www.diku.dk/users/pisinger/95-1.pdf David Pisinger Knapsack problems. — 1995]&lt;br /&gt;
*Silvano Martello, Paolo Toth. Knapsack Problems: Algorithms and Computer Implementations — 1990 г. — ISBN 0-471-92420-2&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Динамическое программирование]]&lt;/div&gt;</summary>
		<author><name>94.25.228.117</name></author>	</entry>

	</feed>