Имя: Пароль:
1C
1С v8
Алгоритм подбора сумма
0 zladenuw
 
03.01.20
10:40
Есть условие

х1+x2+x3+Xn=S;

S= 19;
    
x1 = 30;
x2 = 30;
x3 = 30;

Xn = ...;
Шаг = 0.5;

Нужно получить все возможные варианты сумма чисел, что бы сумма была не больше определенной.
Какие есть идеи.
Какой алгоритм можно использовать.
Спасибо.
И всех с новым годом!
1 Garykom
 
гуру
03.01.20
10:52
(0) х1+x2+x3+Xn=
или все же
х1+x2+x3+...+Xn=
?
2 Asmody
 
03.01.20
10:53
(0) Перебором. Но перебор можно сильно сократить, используя коммутативность сложения.
3 zladenuw
 
03.01.20
10:58
(1) да точечки забыл. спасибо

(2) не вариант, полная формула такая. я там упростил.

она вообще такая ПлотностьПродукции = (ОбъемХ1*ПлотностьХ1+ОбъемХ2*ПлотностьХ2+....+ОбъемN*ПлотностьN)/ОбъемПродукции
Где ПлотностьПродукции  я сравниваю с другим значением. и если они отличаются дальше подбираю значению
4 zladenuw
 
03.01.20
11:00
(2) да пока не пойму как мне Xn сделать перебором
5 Garykom
 
гуру
03.01.20
11:03
(4) Вложенные циклы
6 ДенисЧ
 
03.01.20
11:06
google://задача+о+рюкзаке
7 zladenuw
 
03.01.20
11:12
(6) это да.
Пока думаю как применить это.

   N=3;//количество предметов

    Ves=8;//ограничение на вес рюкзака

    var
    //веса предметов в порядке возрастания, количество экземпляров не ограничено

    M: array[1..N] of integer;
    //стоимости предметов

    C: array[1..N] of integer;
    //T= максимальная ценность рюкзака данного веса

    //если вес набрать нельзя, T=0

    T:array[0..Ves] of integer;
    //номер последнего слагаемого, вошедшего в рюкзак данного веса

    L: array[0..Ves] of byte;
    sum,i,j,v,k,Cmax:integer;
begin
    M[1]:= 2; M[2]:= 4; M[3]:= 6;
    C[1]:= 2; C[2]:= 5; C[3]:= 6;
    //инициализация

    for j:= 0 to Ves do
      begin T[j]:= 0; L[j]:=0; end;

    for j := M[1] to Ves do
      for i := 1 to N do
        begin
+ Code
          if (T[j]<C[i]) and (j=M[i]) then
            //набираем вес одним предметом

            begin
              T[j]:= C[i]; L[j]:=i;
            end
          //i-е слагаемое не превосходит набираемую сумму

          //и набор веса j - M[i] уже существует

          else if (j >= M[i])and (T[j - M[i]]>0) then
            begin
              //добавляем i-е слагаемое к решению

              //и запоминаем его номер

              if  T[j]< T[j - M[i]]+ C[i] then
                begin
                  T[j]:= T[j - M[i]]+C[i]; L[j]:= i;
                end
            end
          //i-е и все последующие слагаемые больше набираемой суммы

          else if (j < M[i]) then break;
        end;

    Cmax:=0; sum:=0;
    //ищем максимум стоимости
    for j:= Ves downto 1 do
      if T[j]> Cmax then
        begin Cmax:=T[j]; sum:=j; end;
    
    //восстанавливаем содержимое максимально ценного рюкзака

    v:=0; k:=0;
    while sum<>0 do
      begin
        i:= L[sum]//i-е слагаемое вошло в рюкзак

        writeln (M[i],' ');
        //уменьшили сумму

        sum := sum - M[i];
        v:=v+M[i]; k:= k+C[i];
      end;
    writeln('Cmax=', k,' ves=',v);
    readln;
end.
8 zladenuw
 
03.01.20
14:04
Что то такое получилось.


Процедура ОсновныеДействияФормыДействие1(Кнопка)
    Сумма = 19;
    
    мМассивВхода = Новый Массив();
    мМассивВхода.Вставить(1,12);
    мМассивВхода.Вставить(2,10);
    мМассивВхода.Вставить(3,0);
    мМассивВхода.Вставить(4,0);
    мМассивВхода.Вставить(5,0);
    мМассивВхода.Вставить(6,0);
    
    МаксУровень = 6;
    Шаг = 0.5;
    
    ТаблицаВариантов = Новый ТаблицаЗначений;
    мМассивШага = Новый Массив();
    Для ы=1 по МаксУровень цикл
        ТаблицаВариантов.Колонки.Добавить("х"+ы);
        мМассивШага.Вставить(ы,0);
    КонецЦикла;
    
    РекурсияСуммВходящих(мМассивВхода, мМассивШага, 0, МаксУровень, Сумма, ТаблицаВариантов, Шаг);
    
    СтрокаГруппировки = "х1";
    
    Для ы=2 по МаксУровень Цикл
        СтрокаГруппировки = СтрокаГруппировки+","+"х"+ы;
    КонецЦикла;    
    
    ТаблицаВариантов.Свернуть(СтрокаГруппировки);    
    
КонецПроцедуры

Процедура РекурсияСуммВходящих(мМассивВхода, мМассивШага, пУровень, МаксУровень, Сумма, ТаблицаВариантов, Шаг)
    
    Если пУровень >= МаксУровень Тогда
        пУровень = 1;
    Иначе
        пУровень = пУровень+1;        
    Конецесли;        
        
    Пока мМассивШага[пУровень] <= мМассивВхода[пУровень] Цикл
        
        Если пУровень <> МаксУровень Тогда
            РекурсияСуммВходящих(мМассивВхода, мМассивШага, пУровень, МаксУровень, Сумма, ТаблицаВариантов, Шаг);
            пУровень = пУровень-1;
        КонецЕсли;
        ДобавитьСумму(мМассивШага, ТаблицаВариантов, Сумма, МаксУровень);
        мМассивШага[пУровень]=мМассивШага[пУровень]+Шаг;        
                        
    КонецЦикла;    
    
    Если пУровень <> 1 Тогда
        мМассивШага[пУровень]=0;
    КонецЕсли;
    
КонецПроцедуры    

Функция ДобавитьСумму(мМассивД, ТаблицаВариантов, Сумма, МаксУровень)
    
    пСумма = 0;
    
    Для ы=1 по мМассивД.Количество()-1 цикл
        Попытка
            пСумма = пСумма+мМассивД[ы];
        Исключение
            пСумма = пСумма+0;
        Конецпопытки;    
    КонецЦикла;
    
    Если пСумма = Сумма Тогда
        НовСтр = ТаблицаВариантов.Добавить();
        Для ы=1 по МаксУровень цикл
            НовСтр["х"+ы]=мМассивД[ы];
        КонецЦикла;
    КонецЕсли;
    
КонецФункции