|
задача о рюкзаках | ☑ | ||
---|---|---|---|---|
0
ЗлобнийМальчик
11.07.12
✎
20:52
|
Есть такая неприятная (для меня) задачка. Уже неделю бьюсь - никак не могу придумать как эффективно решить.
Есть ряд целых чисел a1 - aN и ряд целых чисел W1 - WN. Числа из ряда W1-WN являются суммами чисел а1-аN. Необходимо найти какие числа из ряда а1-аN являются членами каких чисел из ряда W1 - WN. Необходимо найти первый подходящий вариант например ряд чисел 1 1 4 5 6 и второй ряд чисел 6 11. Решением может быть как 6 = 1 + 1 + 4 и 11 = 5+6 так и 6 = 6 и 11 = 1+1+4+5 хоть пните куда читать... |
|||
1
МихаилМ
11.07.12
✎
20:56
|
||||
2
МихаилМ
11.07.12
✎
20:57
|
Вы не полностью описали условия задачи поэтому - (1)
|
|||
3
ЗлобнийМальчик
11.07.12
✎
21:09
|
а какое еще требуется описание?
|
|||
4
serffer
11.07.12
✎
21:09
|
Числа первого ряда(А) должны быть все использованы во втором ряде(W)?
если да то я бы решил примерно так 1. Цикл n по W 2. найдем все варианты(V) решения рюкзака W1 3. для каждого V будем подбирать из оставшихся А Для W2... и так далее 4. если нельзя вычислить ровно на этапе 3, то такой вариант убираем. про рюкзак как написано в вики и большинстве источников мне не нравится. вот http://discopal.ispras.ru/Задача_о_рюкзаке:жадный_алгоритм http://discopal.ispras.ru/Задача_о_рюкзаке:PTAS http://discopal.ispras.ru/Задача_о_рюкзаке:динамическое_программирование |
|||
5
ЗлобнийМальчик
11.07.12
✎
21:11
|
(4) да все числа первого ряда должны быть использованы во втором.
читаю ссылки |
|||
6
МихаилМ
11.07.12
✎
21:26
|
Вы не описали целевую ф-цию
|
|||
7
ЗлобнийМальчик
11.07.12
✎
21:35
|
(6) не совсем вас понимаю. Но если рассматривать данную задачу в классической постановке задачи о рюкзаке, то стоимость чисел равна их величине и необходимо найти оптимальное решение.
|
|||
8
МихаилМ
11.07.12
✎
21:39
|
первый подходящий противоречит - оптимальному решению.
|
|||
9
ЗлобнийМальчик
11.07.12
✎
21:40
|
почему? первый подходящий вариант и будет одним из оптимальных решений?
|
|||
10
МихаилМ
11.07.12
✎
21:47
|
задача о рюкзаке лет 15 как есть в программах изучения всех специальностей связанных и ит.
|
|||
11
ЗлобнийМальчик
11.07.12
✎
21:59
|
я признаю что я плохой программист. Собственно поэтому и обращаюсь на форум - может тут помогут.
|
|||
12
Ненавижу 1С
гуру
11.07.12
✎
22:14
|
первый ряд 1, 3 второй 2, 2 - задача не имеет решения
а вообще динамическое программирование решает проблему |
|||
13
Torquader
11.07.12
✎
22:46
|
На самом деле, как показала практика, то с примерно 10-20 чисел наиболее удачным способом подбора суммы является случайный выбор - один массив из всех чисел - с плавающей границей.
Нижняя часть массива - тестовая сумма (от начала до границы). Если тестовая сумма больше чем надо - то выбираем любой элемент от начала и до границы, переносим его на границу (при этом тот, который был на границе, отправляется на его место - то есть SWAP) и смещаем границу вниз на один элемент (ну и в начало). Если тестовая сумма меньше чем надо - то выбираем любой элемент больше границы и до конца - ставим его следующим на границу (то есть опять делаем SWAP) и смещаем границу на один вверх (ну и в начало). Если сумма совпала - то выходим. Подбирает быстро и хорошо - проверяйте (если, конечно в 1С есть случайное число - я на "Васике" писал - там всё есть). |
|||
14
ЗлобнийМальчик
11.07.12
✎
23:13
|
(12) задача заранее имеет решение - числа из ряда 2 были получены сложением каких то чисел ряда 1
|
|||
15
ЗлобнийМальчик
11.07.12
✎
23:14
|
(13) ща подумаем
|
|||
16
AndyD
12.07.12
✎
10:01
|
исчерпывающий рекурсивный перебор до первого правильного решения
|
|||
17
xenos
12.07.12
✎
10:11
|
Цифра N она приблизительно какая?
|
|||
18
ЗлобнийМальчик
12.07.12
✎
13:18
|
в случае ряда W1 - WN - в пределах десяти
в случае ряда a1 - aN - в пределах тысячи |
|||
19
xenos
12.07.12
✎
13:34
|
(18) >в случае ряда a1 - aN - в пределах тысячи
Тупой перебор займет тысячелетия. Вариантов 2 ^ 1000 Ладно было бы в пределах 10-20 |
|||
20
xenos
12.07.12
✎
13:35
|
"При этом элементарные познания в математике и критическое мышление как бы должны натолкнуть на мысль, что уже на десятом складывании листа, слоёв выходит 1024, а при следующем ? в два раза больше и так далее. Случись, какому-то кузнецу-задроту действительно сложить металл тысячу раз, предполагаемое количество слоев было бы равно 21000 = 1,07e+301 (10301), что, на секундочку, превышает количество атомов в тех ~5 мм толщины лезвия меча, всём мече, его хозяине, земле, солнечной системе и во всей обозримой вселенной, равное всего каким-то 1080 (10 и ещё 79 нулей сзади). "(С)
|
|||
21
NS
12.07.12
✎
13:36
|
(19) Нормально решается рюкзак на тысяче значений.
Простым направленным перебором с отсечениями. |
|||
22
xenos
12.07.12
✎
13:37
|
(21) Так я и говорю про тупой перебор.
|
|||
23
NS
12.07.12
✎
13:38
|
(12) А какое отношение динамическое программирование имеет к задаче о рюкзаке, и к задаче в (0) - которая является тоже чистой задачей о рюкзаке, только ему по-очереди нужно подбирать разные значения суммы.
(22) Ну или Симплекс, что по сути тоже перебор. |
|||
24
ЗлобнийМальчик
12.07.12
✎
13:39
|
(21) дык. Это если один. и если нас устраивают неоптимальные решения. а мне надо фактически произвести дезагрегацию итогов.
Я вообще почитал тут интернеты, и осознал что вообще эта задача скорее про подсуммы. Легче от этого правда не стало |
|||
25
NS
12.07.12
✎
13:39
|
(22) Несколько секунд написанный на 1С-ке занимает как правило перебор на тысяче значений.
|
|||
26
ЗлобнийМальчик
12.07.12
✎
13:44
|
(25) но это для одного значения. А нам то надо чтобы все числа из ряда 1 влезли в ряд два. То есть вполне может оказаться что нам сначала надо получить все варианты для первого числа, потом для каждого из этих варинатов посчитать варианты для второго числа и так далее.
короче это все безумие. Руководство просто с ума сошло - система будет висеть а сэкономим копейки... |
|||
27
NS
12.07.12
✎
13:45
|
(26) Это тоже задача о рюкзаке. Конечно сложность возрастает, но не так страшно. А сколько значений в первом, и сколько во втором ряду?
Какая погрешность допустима, или нужно выходить на суммы копейка-в-копейку? |
|||
28
ЗлобнийМальчик
12.07.12
✎
13:46
|
(27) копейка в копейку
первый ряд порядка до тысячи, второй ряд до 10 |
|||
29
NS
12.07.12
✎
13:48
|
(28) А откуда они знают что сумму можно набрать копейка в копейку?
Вообще - нормально можно считать подряд. Перебираешь начиная с больших значений, и подбираешь начиная с максимальных. На практике будет нормально работать |
|||
30
ЗлобнийМальчик
12.07.12
✎
13:51
|
потому что
|
|||
31
ЗлобнийМальчик
12.07.12
✎
13:51
|
извиняюсь
потому что суммы ряда 2 были получены путем сложения чисел из ряда 1. Это заранее известно |
|||
32
NS
12.07.12
✎
13:52
|
(30) см. (29)
нормально будет работать. Переборный рюкзак с отсечениями начиная с больших значений - я где-то выкладывал. Должен быть в поиске. |
|||
33
ЗлобнийМальчик
12.07.12
✎
13:53
|
ща буду искать
блин как люди до таких знаний дорастают((( |
|||
34
NS
12.07.12
✎
14:03
|
(33) Не то пишу. С левого ряда нужно перебирать начиная с больших, а вот подбираемые, с правого - начиная с меньньших к большим.
Отсечений можно сделать много, но на практике достаточно отсекать если оставшаяся сумма меньше набранной плюс минимальное оставшееся значение, и если набранная сумма больше необходимой. Можно сделать отсечение если сумма всех оставшихся меньше меньше необходимой до добора суммы. Одинаковые значения с левого ряда нужно группировать в пул. |
|||
35
ЗлобнийМальчик
12.07.12
✎
14:36
|
(34) я пока что пытаюсь протестить ваш код из Подскажите алгоритм на 100 значения, 30 суммируемых значениях и одном числе. НО спасибо за наводку
|
|||
36
NS
12.07.12
✎
14:37
|
(35) Это не тот вариант. Это без отсечений, без группировки одинаковых пул, и безз перебора начиная с больших.
|
|||
37
ЗлобнийМальчик
12.07.12
✎
14:41
|
(35) http://abelov.com/kuban/139872.html#11 этот конечно ближе но я хочу сначала простой вариант проверить. все таки в абапе это чуточку по другому выглядит - надо понять как компилятор работает с рекурсией.
|
|||
38
NS
12.07.12
✎
14:45
|
Нужен алгоритм набора нужной суммы
Вот тут правда тоже недоделок - не переписано под массив, и не все отсечения. И задача не подбора точной суммы. |
|||
39
Михаил Козлов
12.07.12
✎
15:58
|
(0) Можно попробовать такой подход (кратко саму идею). Для не слишком большого числа W может оказаться реализуемым.
Если правильно понял, задача формально выглядит как поиск решения системы линейных уравнений с булевыми переменными (специального вида): СУММА(i,j)Ai*Xij=Wj, Xij = {0,1} Xij = 1, если число Ai входит как слагаемое в число Wj (i = 1..N, j = 1..M). Рассмотрим такую функцию (производящая функция числа решений системы уравнений): F(Zj) = ПРОИЗВЕДЕНИЕ(i,j)(1+Zj^Ai). Если в F(Zj) произвести умножение и привести подобные члены, т.е. представить ее в виде полинома: F(Zj) = СУММА(k1,k2..)C(k1,k2..)*Z1^k1*Z2^k2*... то коэффициент C(W1,W2..) - число решений системы. Приведение F(Zj) к "нормальному" виду можно делать последовательно раскрывая скобки и приводя подобные члены. Так что число операций будет порядка N*СУММА(Ai). При этом, т.к. нужно получить лишь одно решение, процесс можно оборвать, как только получится 1 для заданных правых частей системы (W1,...,WM). |
|||
40
Ненавижу 1С
гуру
12.07.12
✎
16:01
|
(23) Задача о ранце в случае, когда вес каждого предмета представляет собой целое число, может быть решена с помощью динамического программирования.
wiki:Задача_о_рюкзаке |
|||
41
NS
12.07.12
✎
16:05
|
(40) Ничего подобного. Задача где каждый предмет не уникальный, а его можно брать неограниченное число раз - можно решить методами динамического программирования. Тут нет такой задачи.
|
|||
42
NS
12.07.12
✎
16:06
|
Причем метод динамического программирования по отношению к стандартному рюкзаку.
|
|||
43
Ненавижу 1С
гуру
12.07.12
✎
16:10
|
(41) не понимаю принципиальной разницы в данном случае
|
|||
44
NS
12.07.12
✎
16:12
|
(43) объясняю - методами динамического программирования задача (41) сводится к обычновенному рюкзаку. Который методами динамического программирования не решается.
|
|||
45
Михаил Козлов
12.07.12
✎
16:12
|
(42) Мне тоже кажется, что динамическое программирование, как общий метод, годится для всего и может свестись к полному перебору.
|
|||
46
Ненавижу 1С
гуру
12.07.12
✎
16:13
|
(44) ну это смотря что иметь ввиду под динамическим программированием
|
|||
47
NS
12.07.12
✎
16:17
|
(44) Да, но обычно динамическим программированием называют методы которые позволяют уйти от полного перебора путем сохранения промежуточных значений при решении подзадачи.
|
|||
48
NS
12.07.12
✎
16:18
|
Честно решить задачу в (0) можно при помощи Гомори.
|
|||
49
Михаил Козлов
12.07.12
✎
16:37
|
(44) Динамическим программированием называют методы, основанные на принципе Беллмана: "Часть оптимальной траектории - оптимальна". Но, по сути, это терминологические заморочки, к сути (трудоемкость) не имеющие отношения.
2 Ненавижу 1С: жду и никак не дождусь Вашего комментария к (39). |
|||
50
NS
12.07.12
✎
16:48
|
(49) Я торможу, никак не могу в него въехать.
// Вообще, в правой части N членов, в левой M получаем NxM неизвестных Aij, каждое принимает значение 0 либо 1. (можем добавить NxMx2 неравенств <=0 и >=0), имеем M равенств, и суммы Ai должны быть равны единице (еще N равенств) И дальше Гомори. |
|||
51
Ненавижу 1С
гуру
12.07.12
✎
16:55
|
(49) сплю что-то
еще должны быть условия СУММА(j)Xij=1 - входит только в одно |
|||
52
Михаил Козлов
12.07.12
✎
17:42
|
(51) Т.е. обязательно входит в одну из сумм?
Формально в производящей функции удвоится число переменных и добавятся сомножители вида (1+Zk) (k=M+1..2M). Трудоемкость увеличится на N*M. Для уравнения X1+X2+...+Xn = W, производящая функция F(Z)=(1+Z)^n. В "нормальном" виде это бином Ньютона и число решений - биномиальные коэффициенты. Если раскрывать скобки и приводить подобные члены, то трудоемкость примерно n^2. Так же и в общем случае: N*сумму всех коэффициентов. Поэтому, для задач с "ограниченными" коэффициентами может сработать. |
|||
53
NS
12.07.12
✎
17:45
|
(52) У него сумма Ai равно сумме Wi
|
|||
54
Михаил Козлов
12.07.12
✎
17:56
|
(53) Если каждое число обязательно куда-то входит по одному разу, то да (похоже на комбинаторные блок-схемы).
А что это меняет? |
|||
55
NS
12.07.12
✎
18:01
|
(54) Мы имеем M+N линейных уравнений с M*N целочисленных неизвестных принимающих значение 0 или 1. (между нулем и единицей)
Больше ничего лишнего в условии нет. |
|||
56
Михаил Козлов
12.07.12
✎
18:25
|
(55) Все, понял. Тупеешь в период закрытия квартала.
|
|||
57
NS
12.07.12
✎
18:35
|
(56) Получаем решение неоднородной системы уравнений, дальше приводим решение к базису. Или я тоже туплю?
|
|||
58
Михаил Козлов
12.07.12
✎
19:11
|
В случае СУММА(j)Xij=1 производящая функция числа решений будет иметь такой вид (явно учтено, что Ai обязательно входит только в одно Wj):
F(Z1,...,Zm) = ПРОИЗВЕДЕНИЕ(i)(Z1^Ai+Z2^Ai+...+Zm^Ai). А дальше раскрывать скобки и приводить подобные члены. В результирующем полиноме членов не более СУММА(Ai), значит и трудоемкость будет примерно такой. |
|||
59
NS
12.07.12
✎
19:21
|
Я так и не понял - почему нельзя просто решить систему линейных уравнений?
|
|||
60
Михаил Козлов
12.07.12
✎
19:24
|
(59) Переменные - 0 или 1, уравнений меньше, чем переменных.
Как Вы собираетесь ее решать? В общем случае это NP-полная задача. |
|||
61
NS
12.07.12
✎
19:37
|
(60) То есть как? Решение неоднородной системы линейных уравнений это NP-полная задача?!
|
|||
62
NS
12.07.12
✎
19:37
|
Сейчас на примере из ноль распишу.
|
|||
63
NS
12.07.12
✎
19:45
|
Уравнение -
1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 1 1 1 1 4 5 6 0 0 0 0 0 6 0 0 0 0 0 1 1 4 5 6 11 |
|||
64
Михаил Козлов
12.07.12
✎
20:01
|
(63) И что с (63) Вы предлагаете делать?
|
|||
65
NS
12.07.12
✎
20:09
|
(64) У меня вообще голова не варит.
Я уж забыл что я хотел. Решаем неоднородную систему, а потом выходит перебор свободных членов :( |
|||
66
Михаил Козлов
12.07.12
✎
20:16
|
(65) Что-то меня все игнорируют. Для примера в (0) производящая функция числа решений будет такая:
F(Z1,Z2) = (Z1+Z2)(Z1+Z2)(Z1^4+Z2^4)(Z1^5+Z2^5)(Z1^6+Z2^6). Почему бы не раскрыть скобки и привести подобные члены? |
|||
67
NS
12.07.12
✎
20:36
|
(66) Раскрыли скобки, а дальше?
|
|||
68
NS
12.07.12
✎
20:41
|
(66) Само раскрытие скобок по ресурсоемкости разве не равно полному перебору?
В общем случае у нас число членов получится 2^N, Для подбора двух сумм. |
|||
69
NS
12.07.12
✎
20:42
|
А нет, О(N)
|
|||
70
NS
12.07.12
✎
21:39
|
А вот теперь я соображаю :)
Решив систему неоднородных уравнений, выведя свободные члены - Мы можем систему равенств превратить в систему неравенств Так как каждое неизвестное >=0 и <=1 Теперь при переборе свободных членов можно максимизировать отсечения. В процессе перебора, зная текущие значения свободных членов можно вычислить максимально и минимально возможные значения выражения. И если минимальное больше единицы, или максимальное меньше нуля - то ветвь отсекаем. |
|||
71
NS
12.07.12
✎
21:47
|
И вообще сначала проходом можем вычислить фиксированные значения, которые не надо проверять.
А затем уже перебирать. Для примера 1,2,5,7. Подбираем 6 и 9 |
|||
72
NS
12.07.12
✎
22:00
|
x1 = 2 x6 + 5 x7 + 7 x8 - 8
x2 = - x6 + 1 x3 = - x7 + 1 x4 = - x8 + 1 x5 = - 2 x6 - 5 x7 - 7 x8 + 9 x6, x7, x8 - свободные переменные. Из первого уравнения x8=1, x7=0, x6=1 Соответственно x1=1 x2=0 x3=1 x4=0 x5=0 то есть 1(x1)1+0(x2)2+1(x3)5+0(x4)7 = 6 матрица была 10001000 1 01000100 1 00100010 1 00010001 1 12570000 6 00001257 9 Проверить решение можно тут http://www.math-pr.com/equations_1.php |
|||
73
NS
12.07.12
✎
22:10
|
Короче - нужна компонента для решения разряженной системы неоднородных линейных уравнений.
И после её использования уже можно делать нормальный перебор. |
|||
74
NS
13.07.12
✎
02:00
|
Есть оказывется методы решения неравенств в целых числах. Например метод фурье-моцкина.
|
|||
75
NS
13.07.12
✎
02:41
|
При двух числах в правом ряду - задача превращается в чистый рюкзак, соответственно сложность алгоритма решения не может быть лучше чем у рюкзака. Отличие от рюкзака только в том что подбирать сумму нужно точную, и мы точно знаем что она подбирается.
|
|||
76
Злопчинский
13.07.12
✎
04:05
|
чувствую себя мелким муравьем...
|
|||
77
izekia
13.07.12
✎
04:08
|
(76) зато в соседней теме ты крут
|
|||
78
vah1
13.07.12
✎
06:39
|
имхо надо сначала одиночные совпадения из ряда 1 и ряда 2, а потом уже тупо перебирать, и какая разница что во втором ряду и 6 и 11 подходят, если это в условиях не прописано (как например 11 и 11, первую брать или вторую)
|
|||
79
vah1
13.07.12
✎
06:41
|
+ исключить
|
|||
80
Михаил Козлов
13.07.12
✎
10:36
|
(0) Готов сделать как в (39), (58). Только подтвердите, что это действительно нужно. Мыло в профиле.
|
|||
81
NS
13.07.12
✎
10:54
|
(80) В (39) и (58) 100% ошибка как минимум в сложности алгоритма.
Сумма чисел слева равна сумме чисел справа. Поэтому второе условие мы можем убрать и получаем чистый рюкзак. Насчет динамического программирования вспомнил - оно применяется при небольшой дискретной вместимости ранца. Сложность алгоритма решения тогда О(количество_Предметов*вместимость_ранца) |
|||
82
Михаил Козлов
13.07.12
✎
12:41
|
(81) Сложности не вижу. Обычно (было уже раза 4) после предложения топикстартеру поковыряться с задачей обращений нет. Видимо, задача не слишком актуальна или возможны другие подходы.
|
|||
83
NS
13.07.12
✎
12:53
|
(82) N*СУММА(Ai) - действительно похоже на правду. Такую-же сложность даст решение динамическим программированием.
|
|||
84
NS
13.07.12
✎
12:59
|
Хотя что-то не то я нашел. Динамическим программированием экспоненциальна сложность решения. У нас все наборы хранятся. А их экспоненциальное количество.
То есть сложности указанной в (39) Быть не может. Такая сложность только если мы каждый предмет можем брать неограниченное число раз. |
|||
85
Михаил Козлов
18.07.12
✎
21:25
|
Сделал в 1С как в (58). Немного погонял, итги неутешительные: для N=1000 и М=10 работать вряд ли будет.
100х2: 1 сек. 150х2: 1 сек. 200х2: 2 сек. 250х2: 2 сек. 300х2: 3 сек. 350х2: 5 сек. 400х2: 6 сек. 450х2: 8 сек. 500х2: 10 сек. 1000х2: 39 сек. 100х3: 25 сек. 150х3: 87 сек. 200х3: 201 сек. 250х3: 404 сек. 300х3: 699 сек. 100х4: 1 081 сек. Сложность O((N*M)^2). Основное время тратилось на построение ключа для монома Z1^k1*...*ZM1^kM. |
|||
86
NS
18.07.12
✎
21:36
|
(85) Ну не может рюкзак с такой сложностью решаться.
А в (0), при двух набираемых суммах - чистый рюкзак. |
|||
87
Михаил Козлов
19.07.12
✎
10:29
|
Проврался с трудоемкостью в (85): O(N^M). Трудоемкость определяется количеством членов в полиноме (58), оно порядка числа решений K1+...+KM = N - это полиномиальный коэффициент, т.е. O(N^M).
(86) Согласен (если решать, как в (58) можно M увеличить на 1, но не более), но для M=2 и в (58) получается O(N^2), а это приемлимо. В общем, для характеристик в (0) (N=1000, M=10) этот метод не сработает. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |