Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Заметание






Рассмотрим следующую задачу.

Закраска прямой. На числовой прямой окрасили N отрезков. Известны координаты левого и правого концов каждого отрезка (Li и Ri). Найти длину окрашенной части числовой прямой.

Ограничения: Li и R i - целые, -1000 ≤ Li ≤ Ri ≤ 1000, 1 ≤ N ≤ 1000, время 1 с.

Ввод из файла INPUT.TXT. В первой строке находится число N, в следующих N строках - пары Li и R i.

Вывод в файл OUTPUT.TXT. Вывести одно число – длину окрашенной части прямой.

Примеры

Ввод 1 Ввод 2

2 1

1 3 10 10

2 4

Вывод 1 Вывод 2

3 0

 

Отсортируем концы отрезков по возрастанию. Будем просматривать отсортированный массив слева направо, прибавляя к счетчику 1 в случае начала отрезка, и вычитая 1 для конца отрезка. Если счетчик получает значение 1 в начале очередного отрезка, запомним соответствующее значение координаты L. Если счетчик становится равным 0 в некотором конце отрезка с координатой R, то очередное объединение отрезков закончилось, и точки до следующего начала отрезка не принадлежат ни одному отрезку. Прибавляем величину R-L к общей длине окрашенной части.

Приведем текст программы для решения этой задачи.

 

Program PaintX;

Const

Max=2000;

Type

Segm=record

X: integer; {координата}

Vid: integer; {1-левый конец, -1-правый}

end;

Var

M, N, i, j, K, L: integer;

Lp: longint; {общая длина окрашенной части прямой}

S: array [1..Max] of Segm;

Fin, Fout: text;

Procedure Sort; {сортировка на месте}

Var

i, j: integer;

B: Segm;

Begin

For i: =2 to K do

For j: =K downto i do { пузырек }

if (S[j].X< S[j-1].X) then

begin

B: =S[j];

S[j]: =S[j-1];

S[j-1]: =B;

end;

End;

 

Begin

Assign(Fin, 'input.txt');

Reset(Fin);

ReadLn(Fin, N);

K: =0; {число концов}

For i: =1 to N do

begin

K: =K+2;

ReadLn(Fin, S[K-1].X, S[K].X);

S[K-1].Vid: =1; {признак левого конца}

S[K].Vid: =-1; {признак правого конца}

end;

Close(Fin);

Sort;

Lp: =0; {общая длина окрашенной части прямой}

M: =0; {количество отрезков, содержащих текущую координату}

For i: =1 to K do

begin

M: =M+S[i].Vid;

if (M = 1) and (S[i].Vid = 1) then L: =S[i].X;

if (M = 0) and (S[i].Vid = -1) then Lp: =Lp+S[i].X-L;

end;

Assign(Fout, 'output.txt');

Rewrite(Fout);

Write(Fout, Lp);

Close(Fout);

End.

При увеличении размерности необходимо использовать один из вариантов быстрой сортировки.

В рассмотренной задаче мы продвигаемся по числовой прямой, обрабатывая два вида событий: начало и конец какого-либо отрезка. Между точками событий принципиально ничего не изменяется.

Подобный подход называют методом заметания (выметания, скользящей прямой, sweeping). Обычно он включает в себя следующие этапы:

· выделение точек событий;

· сортировка точек событий;

· последовательное продвижение по точкам событий с обработкой точек в зависимости от вида событий.

В нашей задаче всего два вида событий, но их может быть и больше.


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.006 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал