Имя: Пароль:
1C
1С v8
Задача о ранце без стоимости
, ,
0 zhig75
 
05.02.16
12:21
Привет. Я сломался.
Есть некое множество чисел в таблице, из которых надо оптимально выбрать значения которые в сумме дадут <= необходимую сумму.
Нужен алгоритм для восьмерки.
Нашел вот это Нужен алгоритм набора нужной суммы, но что-то ничерта не могу понять поскольку для 7.
1 Михаил Козлов
 
05.02.16
12:31
Жадным алгоритмом попробуйте: упорядочить по убыванию, добавлять очередное, если возможно.
2 zhig75
 
05.02.16
12:35
(1) А пример есть?
3 mistеr
 
05.02.16
12:41
Задача о ранце без стоимости подобна задаче о ранце со стоимостью, только... Без только, это она и есть.
4 Михаил Козлов
 
05.02.16
12:45
Какой еще пример нужен: там 5 строчек кода.
Если на тестовых примерах будет плохо подбирать, тогда нужно будет смотреть, как улучшить (литературы по ранцу полно. На форуме есть участник NZ или NS - не помню - который с ранцем плотно возился).
Вы для начала озвучьте порядок количества чисел.
5 zhig75
 
05.02.16
12:51
(4) К примеру 40 различных чисел, 123, 434, 5943, 334, 4322, 4343, 4445, 4303, итд, из них надо выбрать числа которые в сумме дадут <= 24500
6 zhig75
 
05.02.16
12:52
(4) Пока на ум приходит Цикл в Цикле для каждого значения.
7 Михаил Козлов
 
05.02.16
12:58
(6) Пусть числа хранятся в ТЗ.

ТЗ.Сортировать("Сумма УБЫВ");
решение = Новый Массив; подобрано = 0;
ДЛЯ каждого стр ИЗ ТЗ Цикл
  Если подобрано+стр.Сумма<=нужнаяСумма Тогда
    подобрано = подобрано+стр.Сумма;
    решение.Добавить(стр);
  КонецЕсли;
КонецЦикла;
8 ObjectRelation Model
 
05.02.16
13:00
(7) необязательно будет лучший результат
9 zhig75
 
05.02.16
13:05
(7) Ну отберет этот цикл из первых чисел, результат не оптимален.
10 Ma3eIIa
 
05.02.16
13:12
(9) почему из первых ?
ты внимательно читал ?
11 Ma3eIIa
 
05.02.16
13:16
Пусть задана пара (S, t), где S = {x1, x2, …, xn} представляет собой множество положительных целых чисел, а t — положительное целое число. Требуется отыскать среди подмножеств множества S, сумма которых не превосходит t, такое, у которого сумма ближе всего к t.

Пусть |S| = n. Обозначим (k, w) — задачу, в которой имеется k первых чисел из S и нужно набрать сумму w. Таким образом исходная задача — это задача (n, t).

Для решения задачи построим таблицу T[n, t + 1], в клетку T[i, j] которой будем записывать оптимальное решение задачи (i, j).

Первый столбец заполним нулями. Первую строку заполним сначала нулями, а начиная с клетки (1, x1) — числами x1. Клетку T[i, j] (i, j > 1) будем заполнять по правилу:

Если j ? xi > 0, то y := T[i ? 1, j ? xi], иначе y := 0;
T[i, j] := max(T [i ? 1, j], y + xi)
12 samozvanec
 
05.02.16
13:16
(10) нужно косарь, числа 970, 960, 40, 20
13 Ma3eIIa
 
05.02.16
13:18
вот еще. о гугл. ты могуЧ.

http://fixin.com.ru/articles/alg_makesumm/article.htm
14 Ma3eIIa
 
05.02.16
13:21
ну или вот 1 в 1.
const
    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
          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.
15 Михаил Козлов
 
05.02.16
13:25
(8) Кто бы спорил.
(11) Если не ошибаюсь (могу, в таком разе извините), это метод динамического программирования применительно к задаче о ранце. Как известно, может работать экспоненциально долго. Чтобы не разводить холивар: про ранец довольно много чего известно, вряд ли удастся изобрести что-то новое: проще найти.
16 Ma3eIIa
 
05.02.16
13:34
(15) 100500 :). математический алгоритм 1.
Знаю что в битах обработках будет быстрее
17 Ma3eIIa
 
05.02.16
13:36
18 Ma3eIIa
 
05.02.16
13:43
вот еще можно почитать

http://dic.academic.ru/dic.nsf/ruwiki/1793823

а так гуглить можно вечно :)
19 samozvanec
 
05.02.16
13:58
(18) харош уже. все хотели просто пофлеймить, а ты вариантов накидал аки профессор. ТС вообще сказал, что "алгоритм для 77 сложна, дайти на 8ку"
20 Ma3eIIa
 
05.02.16
14:10
(19) это было к (15) . вопрос по оптимизации и скорости получение результата :)
Да я себе заметки тут оставил :)
21 su_mai
 
05.02.16
14:17
(8) Будет лучший вариант если исходное множество - матроид
22 Михаил Козлов
 
05.02.16
14:27
(21) К сожалению, ранец не матроид.
Матроиды вообще нынче редки :-)