Имя: Пароль:
1C
1C 7.7
v7: Рюкзак!
Ø (GROOVY 02.12.2011 18:16)
0 TwoWorld
 
16.11.11
15:52
Цель: есть машина (известен объем и вес машинны), необходимо подобрать заявки в эту машину!

Перем ЛучшаяГрузоподъмностьМашиныДельта,ЛучшийОбъемМашиныДельта;
Перем ТЗ;

   ОбъемМашины = Автомобиль.ОбъемКузова;
   ГрузоподъмностьМашины = Автомобиль.Грузоподъмность;
   ЛучшийОбъемМашины = 0;
   ЛучшаяГрузоподъмностьМашины = 0;
   ЛучшийОбъемМашиныДельта = Автомобиль.ОбъемКузова;
   ЛучшаяГрузоподъмностьМашиныДельта = Автомобиль.Грузоподъмность;
   
   ТЗ.Сортировать("ВесБрутто-,Объем-");
   ТЗ.Заполнить(0,,,"ТемпОбъем,ТемпВес,ВыбОбъем,ВыбВес");
   Рюкзак(ТЗ,ОбъемМашины,ГрузоподъмностьМашины);
   ТЗ.Заполнить(0,,,"ТемпОбъем,ТемпВес");


Функция Рюкзак(ТЗ,ОбъемМашины,ГрузоподъмностьМашины,знач нач=0)
    Если (ОбъемМашины = 0) и (ГрузоподъмностьМашины = 0) Тогда
        ТЗ.ВыбратьСтроки();
        Пока ТЗ.ПолучитьСтроку()=1 цикл
            ТЗ.ВыбОбъем = ТЗ.ТемпОбъем;
            Тз.ВыбВес = ТЗ.ТемпВес;
        КонецЦикла;    
        ЛучшаяГрузоподъмностьМашиныДельта = 0;
        ЛучшийОбъемМашиныДельта = 0;
        возврат 0; // нашли точное соответствие
    ИначеЕсли (ОбъемМашины < 0 ) и (ГрузоподъмностьМашины < 0 ) Тогда
        возврат 1;  // перебор
    ИначеЕсли (ОбъемМашины < ЛучшийОбъемМашиныДельта) и (ГрузоподъмностьМашины < ЛучшаяГрузоподъмностьМашиныДельта) Тогда    
        ТЗ.ВыбратьСтроки();
        Пока ТЗ.ПолучитьСтроку()=1 цикл
            ТЗ.ВыбОбъем = ТЗ.ТемпОбъем;
            ТЗ.ВыбВес = ТЗ.ТемпВес;
        КонецЦикла;    
        ЛучшийОбъемМашиныДельта = ОбъемМашины;
        ЛучшаяГрузоподъмностьМашиныДельта = ГрузоподъмностьМашины; // улучшили решение
    КонецЕсли;
    Если нач=ТЗ.КоличествоСтрок() Тогда
        возврат 1; // пробежали до конца
    КонецЕсли;    
    нач=нач+1;  
// ТУТ ГДЕТО ОШИБКА НЕ МОГУ РАЗОБРАТЬСЯ//////////////////////////
    а = ТЗ.ПолучитьЗначение(нач,"Объем");
    в = ТЗ.ПолучитьЗначение(нач,"ВесБрутто");
    Пока (а>=0)  и (в>=0) цикл  
        ТЗ.УстановитьЗначение(нач,"ТемпОбъем",а);
        ТЗ.УстановитьЗначение(нач,"ТемпВес",в);
        Если Рюкзак(ТЗ,ОбъемМашины-ТЗ.ПолучитьЗначение(нач,"Объем"),ГрузоподъмностьМашины-ТЗ.ПолучитьЗначение(нач,"ВесБрутто"),нач)=0 Тогда
            возврат 0;  
        КонецЕсли;    
    КонецЦикла;    
    возврат 1;
КонецФункции

Подскажите где в функции ошибки?
1 TwoWorld
 
16.11.11
15:53
Если Рюкзак(ТЗ,ОбъемМашины-ТЗ.ПолучитьЗначение(нач,"Объем"),ГрузоподъмностьМашины-ТЗ.ПолучитьЗначение(нач,"ВесБрутто"),нач)=0 Тогда

Например: ОбъемМашины = 23,ТЗ.ПолучитьЗначение(нач,"Объем") = 25 , следовательно получается минус и все!!!!!!!!!!!!!!
2 Ёпрст
 
16.11.11
16:06
лень смотреть, отладчик рулит в таких случаях
3 orefkov
 
16.11.11
16:07
(0)
NS у нас знатный "турист" по рюкзакам - его пытай.
4 TwoWorld
 
16.11.11
16:13
(2) не лень , я сам писал почти весь код, прост никак не разберусь с этой засадой
5 palpetrovich
 
16.11.11
16:16
"Рюкзак" вызывается рекурсивно, это так задумано или сюда скопипастено неверно?
6 Злопчинский
 
16.11.11
16:16
набираем в вики "задача о рюкзаке" - там есть все что надо...
на основе NS-рекурсивного алгоритма у меня заявка бъется по палетам.
Объем набирать "кучей" - можно сильно промахнуться...
www.packer3d.ru
7 TwoWorld
 
16.11.11
16:19
У меня в заявке есть объем и вес заявки, следовательно есть автомобиль - у него проставлено вес и объем и мне нужно набрать....вроде как (0) все нормально набирает, только вот (1) есть такой косяк
8 Ёпрст
 
16.11.11
16:20
(7) у тебя как минимум, есть моменты, когда в самый низ проваливается сразу
9 TwoWorld
 
16.11.11
16:20
(8) т.е в самый низ?
10 Ткачев
 
16.11.11
16:53
11 TwoWorld
 
16.11.11
17:10
ды код то не надо менять , он правильно работает, только вот (1) глючит на "-"
12 polymorph
 
16.11.11
17:20
(11) правильно работает, но только глючит на "-" - называется неправильно работает
13 TwoWorld
 
16.11.11
17:46
просто вот тут нуно как то подправить:
   а = ТЗ.ПолучитьЗначение(нач,"Объем");
    в = ТЗ.ПолучитьЗначение(нач,"ВесБрутто");
    Пока (а>=0)  и (в>=0) цикл  
         ТЗ.УстановитьЗначение(нач,"ТемпОбъем",а);
         ТЗ.УстановитьЗначение(нач,"ТемпВес",в);
        Если Рюкзак(ТЗ,ОбъемМашины-ТЗ.ПолучитьЗначение(нач,"Объем"),ГрузоподъмностьМашины-ТЗ.ПолучитьЗначение(нач,"ВесБрутто"),нач)=0 Тогда
            возврат 0;  
        КонецЕсли;    
    КонецЦикла;    
    возврат 1;
КонецФункции
14 Ёпрст
 
16.11.11
17:46
(13) догадливый однако
15 Ткачев
 
16.11.11
19:59
Функция Рюкзак(ТЗ,ОбъемМашины,ГрузоподъмностьМашины,ЗНАЧ НАЧ=0)
...
НАЧ = НАЧ + 1;
...
У тебя НАЧ не меняется и всегда = 1
16 ildary
 
02.12.11
13:42
Апну тему: уважаемые специалисты, а как называется (или ключевые слова для поиска) решение задачи, подобной рюкзаку, когда надо не просто разложить товар по машине, но и при этом минимизировать количество машин, вот пример:

Есть груз общим весом 1500 + 500 = 2000 кг (сумма двух заказов)
есть две машины, первая (М1): макс.вес=1500 кг, вторая (М2) - макс.вес=3000 кг. При загрузке компьютер старается заполнить машину по максимуму, поэтому он распределяет так: М1: 1500, М2: 500 (недогруз 2500). В то время как было бы правильно послать только М2 с недогрузом 1000 кг. Но раз он на каждом проходе выбирает только одну машину, то он решает, что загрузить М1 по самую крышу - это лучшее, что можно сделать.
Чтобы понять, как это сделать надо хотя бы слова ключевые, а с этим - напряг.
17 Базис
 
naïve
02.12.11
14:16
(16) Задача линейного программирования.
Что-то типа функции Издержки() составь и её минимизируй. Только, кажется, она должна быть линейной. Ну, может, кусочно-линейной - хотя при этом расчёт надо повторить для каждого куска линейности целевой функции.
18 Михаил Козлов
 
02.12.11
15:56
(17) Не совсем, т.к. нельзя использовать 1,5 машины.
(16) Могу попробовать ветвями и границами. если пришлете пример исходных данных (мыло в профиле).
19 G-Re
 
02.12.11
18:08
Есть старая книжка
И.В. Романовский "Алгоритмы решения экстремальных задач",М.Наука,1977.
Там много формулировок и решений дискретных оптимизационных задач, тексты на Алголе.