Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1 Программирование на Паскаль.doc
Скачиваний:
18
Добавлен:
26.04.2019
Размер:
1.18 Mб
Скачать

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

program pohod_rec;

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);

min:= MaxLongInt;

step(1,0);

writeln('difference ',min)

end.

Полный перебор с отсечением

Приведенная выше программа делает много лишней работы. Скажем, незачем продолжать генерирование очередного набора после того, как текущая разность уже превысила ранее найденный минимум. Кроме того, если в некоторый момент времени минимум вдруг окажется равным 1 или 0 (в зависимости от четности входных данных), то дальнейшие усилия также становятся ненужными, поскольку все равно ничего меньшего быть не может.

С учетом этих замечаний можно усовершенствовать текст программы. Мы оставляем эту несложную работу желающим.

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

Здесь нам потребуется несколько дополнительных рассуждений и линейных массивов.

Основная часть приводимой ниже программы является итеративной реализацией алгоритма полного перебора всех возможных вариантов, удовлетворяющих входным ограничениям. Ее основное отличие от рекурсии - использование малого объема памяти для хранения текущих данных. Вся информация хранится в массивах ves, take и dif. Для вычислений на каждом шаге используется только эта информация. Такой подход позволяет избежать непрерывных перевычислений, которые и являются причиной "тяжеловесности" рекурсивного алгоритма.

Итак, первая часть программы должна заниматься подсчетом и упорядочением вводимых предметов по убыванию их весов. Для экономии места мы не станем приводить подробную реализацию этого блока: здесь годится любой метод сортировки (см. лекцию 4). Важно лишь, что в результате этой сортировки все входные данные будут записаны в два линейных массива длины k (количество разных весов).

Считаем теперь, что массив ves хранит различные веса предметов, упорядоченные по убыванию, а массив kol - количество предметов каждого веса.

Кроме того, в процессе ввода данных производится суммирование весов всех предметов, этот общий вес записывается в переменную sum. Правда, затем эта же переменная будет хранить не весь общий вес, а только его половину (с учетом четности исходной суммы) - для удобства дальнейших сравнений.

Мы не приводим в тексте программы и реализацию функции min() - как не представляющую особенного интереса.

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

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.