Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Derevo.doc
Скачиваний:
5
Добавлен:
08.08.2019
Размер:
147.97 Кб
Скачать

Пусть имеется семь предметов (n = 7) с весами 9, 5, 25, 11, 9, 5, 11.

Тогда всего есть четыре разных по весу предметов (k = 4).

Общая сумма весов равна 75;  "большая половина" sum = 38.

Нужно найти такой набор предметов, чей суммарный вес будет ближе всего к этой "золотой середине". Кроме того, как только найдется набор, вес которого отличается от "золотого" лишь на 1, поиск можно закончить.

Заполним массивы take и dif (dif хранит остатки, в пределах которых можно проводить дальнейшие вычисления).

На начальном ("0-м") шаге заполним массив take так, чтобы в создаваемый набор попали самые тяжелые предметы.

Таким образом, состояния массивов:

ves - 25 11 9 5

take 0 1 1 0 0

dif 38 13 2 0 0

После этого шага переменная razn, которая хранит отклонение текущего набора весов от

оптимального, будет содержать значение 2. Попытаемся уменьшить это значение.

Двигаясь от конца массива take к его началу, будем уменьшать поочередно каждую его ненулевую компоненту. При этом будут возникать изменения в хвосте этого массива; эти изменения мы будем вносить туда в последовательности "от начала к концу".

Массивы примут значения:

1

ves - 25 11 9 5

take 0 1 0 1 0

dif 38 13 13 4 0

2

ves - 25 11 9 5

take 0 1 0 0 2

dif 38 13 13 13 3

3

ves - 25 11 9 5

take 0 1 0 0 1

dif 38 13 13 0 8

4

ves - 25 11 9 5

take 0 1 0 0 0

dif 38 13 13 13 13

5

ves - 25 11 9 5

take 0 0 2 1 1

dif 38 38 16 7 2

...

24

ves - 25 11 9 5

take 0 0 0 0 0

dif 38 38 38 38 38

Найденное в начале значение razn было минимальным, группы весов соответственно

25 + 11 = 36 и 11 + 9 + 9 + 5 + 5= 39.

Из приведенных данных видно (см. шаг 5), что существует еще один способ разделить приведенный набор весов таким же оптимальным образом:

11 + 11 + 9 + 5 = 36 и 25 + 9 + 5 = 39.

Найденная разница 39 - 36 = 3 окончательный результат, который программа сообщит пользователю.

Вся информация хранится в массивах ves, take и dif. Первая часть программы должна заниматься подсчетом и упорядочением вводимых предметов по убыванию их весов. Любым методом сортировки. В результате этой сортировки все входные данные будут записаны в два линейных массива длины k (количество разных весов). Считаем, что

Ves - хранит различные веса предметов, упорядоченные по убыванию,

kol - количество предметов каждого веса.

В процессе ввода данных производится суммирование весов всех предметов (sum). Затем эта переменная будет хранить его половину (с учетом четности исходной суммы) – для удобства дальнейших сравнений.

Реализация нерекурсивного алгоритма

program pohod;

const nnn = 100; {максимально возможное количество различных весов}

var f: text;

d,razn,k,i,j,n: integer;

sum: longint;

ves,kol: array[1..nnn] of word;

take, dif: array[0..nnn] of word;

procedure vyvod(a: integer);

begin

writeln(a);

halt;

{принудительное завершение работы программы}

end;

begin

{---- Ввод данных и их сортировка ---}

...

{---- Основная часть программы -----}

d:= sum mod 2;

{показатель четности общего веса}

sum:=(sum div 2)+ d;

{"большая половина" общего веса}

dif[0]:= sum;

razn:= sum;

for i:= 1 to k do

begin

take[i]:= min(dif[i-1] div ves[i], kol[i]);

dif[i]:= dif[i-1]- take[i]*ves[i];

if dif[i]< razn then razn:= dif[i];

if razn <= d then vyvod(d);

{проверка того, что уже на первом шаге найдено решение}

end;

{---- Заполнение массива --------}

i:= k;

while i>0 do

begin

if take[i]= 0 then i:= i-1

{переход к следующей компоненте}

else begin

dec(take[i]);

{уменьшение текущей компоненты на 1}

inc(dif[i],ves[i]);

{увеличение остатка на соотв.

величину}

for j:= i+1 to k do

{перезаполнение хвоста}

begin

take[j]:= min(dif[j-1] div ves[j], kol[j]);

dif[j]:= dif[j-1]- take[j]*ves[j];

if dif[j]< razn then razn:= dif[j];

if razn <= d then vyvod(d);

{проверка результата}

end;

i:= k;

end; end; vyvod(2*razn-d); end.

Рекурсивный алгоритм

program turIst;

var f: text;

a: array[1..100] of integer;

n: integer;

min,obsh_ves: longint;

procedure step(t:byte; ves:longint);

var j: longint;

begin

j:= abs(obsh_ves - 2*ves);

if j<min then min:= j;

for j:= t+1 to n do step(j,ves+a[t]);

end;

begin

assign(f,'in'); reset(f);

n:=0; {кол-во всех предметов}

obsh_ves:= 0;

while not eof(f) do

begin

inc(n); read(f,a[n]); inc(obsh_ves,a[n]);

end;

close(f);

writeln ('obsh_ves=', obsh_ves);

min:= MaxLongInt; writeln (min);

step(1,0);

writeln('difference ',min)

end.

Дерево — это иерархическая структура данных, состоящая из элементов (вершин, или узлов), которые связаны между собой отношениями типа «родительская вершина – дочерняя вершина».

Определить дерево с вершинами типа T можно следующим образом:

  1. это либо пустое дерево, не содержащее ни одной вершины;

либо некоторая вершина типа T, соединенная ветвями с конечным числом отдельных деревьев с вершинами типа T (эти деревья называются поддеревьями).

Чаще всего дерево изображается в виде графа, вершинами которого являются вершины дерева, а ребрами — его ветви.

Начальная вершина дерева, называемая корнем, изображается в верхней части графа, и считается, что она находится на нулевом уровне.

Вершина Y, расположенная ниже вершины X и соединенная с ней ветвью, называется непосредственным потомком вершины X, или ее дочерней вершиной (а вершина X, соответственно, — непосредственным предком вершины Y, или ее родительской вершиной).

Узел A является корнем, который имеет два поддерева { B } и { C , D , E , F , G }. Корнем дерева { C , D , E , F , G } является узел C .

Уровень узла C равен 1 по отношению ко всему дереву. Он имеет три поддерева { D }, {E}и { F , G }, поэтому степень узла C равна 3.

Концевыми узлами (листьями) являются узлы B , D , E , G .

Путем из узла n 1 в узел n k называется последовательность узлов n 1 , n 2 , … n k , где для всех i , 1<i < k , узел n i является родителем узла n i +1 .

Длиной пути называется число, на единицу меньшее числа узлов, составляющего этот путь.

Таким образом, путем нулевой длины будет путь из любого узла к самому себе. Например, на рисунке путем длины 2 будет путь от узла A к узлу F или от узла C к узлу G.

Высотой узла дерева называется длина самого длинного пути от этого узла до какого-либо листа.

Глубина узла определяется как длина пути от корня до этого узла.

Лес – это множество (обычно упорядоченное), содержащее несколько непересекающихся деревьев. Узлы дерева при условии исключения корня образуют лес

Порядок узлов

Если в определении дерева имеет значение порядок поддеревьев T1 , T2 , ... Tm , то дерево является упорядоченным.

Потомки узла обычно упорядочиваются слева направо. Поэтому деревья, приведенные на рисунке, являются различными.

Если порядок потомков игнорируется, то такое дерево называется неупорядоченным. Далее будем неявно предполагать, что все рассматриваемые деревья являются упорядоченными, если явно не указано обратное.

Обходы дерева

Существует несколько способов обхода всех узлов дерева. Три наиболее часто используемых способа обхода называются прямой, обратный и симметричный обходы.

Все три способа можно рекурсивно определить следующим образом:

Если дерево T является нулевым деревом, то в список обхода записывается пустая строка;

Если дерево T состоит из одного узла, то в список обхода записывается этот узел;

Пусть дерево T имеет корень n и поддеревья T1 , T2 , ... Tm , как показано на рисунке

Тогда для различных способов обхода имеем следующее:

Прямой обход. Сначала посещается корень n , затем в прямом порядке узлы поддерева T1 , далее все узлы поддерева T2 и т.д. Последними посещаются в прямом порядке узлы поддерева Tm .

Обратный обход. Сначала посещаются в обратном порядке все узлы поддерева T1 , затем в обратном порядке узлы поддеревьев T2 … Tm , последним посещается корень n .

Симметричный обход. Сначала в симметричном порядке посещаются все узлы поддерева T1 , затем корень n , после чего в симметричном порядке все узлы поддеревьев T2 … Tm .

Пример всех способов обхода дерева, изображенного на рисунке:

Порядок узлов данного дерева в случае прямого обхода будет следующим: 1 2 3 5 8 9 6 10 4 7.

Обратный обход этого же дерева даст нам следующий порядок узлов: 2 8 9 5 10 6 3 7 4 1.

При симметричном обходе мы получим следующую последовательность узлов: 2 1 8 5 9 3 10 6 7 4.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]