"Прямоугольники"
С.М.Окулов
На плоскости задано N (1
ЈNЈ300) прямоугольников со сторонами, параллельными координатным осям (см. рисунок). Координаты вершин прямоугольников – вещественные числа, заданные с точностью до двух знаков после запятой. Написать программу определения площади фигуры, получающейся в результате объединения прямоугольников.
Входные данные. В первой строке файла INPUT.TXT записано число N. В следующих N строках записано по четыре числа – координаты левого нижнего и правого верхнего углов прямоугольника.
Выходные данные. В файле OUTPUT.TXT записывается одно число – площадь фигуры с точностью до четырех знаков.
Пример
Входные данные
4
0 0 10.1 5.2
-3 3 5.36 7
1 6 9 15
8 3 20 8
Выходные данные
195.188
Идея решения
Продлим все вертикальные стороны прямоугольников до пересечения с осью X. Этим мы определим на оси X множество интервалов, внутри каждого из которых длина сечения по оси Y будет постоянной (см. рисунок).
Поэтому для нахождения площади достаточно отсортировать точки на оси X, рассмотреть все сечения и добавить к площади <длину интервала>•<длину сечения>. Для поиска длины сечения используем следующий метод. Началу каждого отрезка присвоим значение признака, равное 1, а его концу –1 и отсортируем точки по значению координаты Y. Подсчитаем сумму значений признаков. Если она не равна нулю, то соответствующий интервал “плюсуем” к длине сечения.
Структуры данных
Const InputFile='Input.TxT';
OutputFile='Output.TxT';
MaxN=300;
Eps=1e-5;
Tochn=4;
Type TPoint=Record X,Y:Real;End;
MasPnt=Array[1..MaxN] Of TPoint;
BMasPnt=Array[1..MaxN*2] Of Real;
BMasSSt=Array[1..MaxN*2] Of LongInt;
Var PrM: Array[1..2] Of MasPnt;
N: LongInt;
Res: Real;
Ox, Oy: BMasPnt;
FOy: BMasSSt;
Процедура инициализации и ввода данных
Координаты вершин прямоугольников храним в массиве PrM, причем в PrM[1] (это массив) – координаты первой вершины, а в PrM[2] – второй. Вершина прямоугольника с меньшими значениями (X, Y) записывается в PrM[1]. Кроме того, значения X запоминаются в массиве Ox. Procedure ReadPoint(Var A: TPoint);Procedure More(Const a, b: Real): Boolean;
Begin
More:=a-b>Eps;
End;
Procedure Init;
Var i: LongInt;
Begin
Res:=0;
FillChar(Ox, SizeOf(Ox), 0);
FillChar(Oy, SizeOf(Oy), 0);
FillChar(Foy, SizeOf(FoY), 0);
FillChar(PrM, SizeOf(PrM), 0);
Assign(Input, InputFile);Reset(Input);
Read(N);
For i:=1 To N Do Begin
ReadPoint(PrM[1,i]);ReadPoint(PrM[2,i]);
If More(PrM[1,i].X, PrM[2,i].X)
Then Swap(PrM[1,i].X, PrM[2,i].X);
If More(PrM[1,i].Y, PrM[2,i].Y)
Then Swap(PrM[1,i].Y, PrM[2,i].Y);
Ox[i*2-1]:=PrM[1,i].X;Ox[i*2]:=PrM[2,i].X;
End;
Close(Input);
End;
Процедура вывода результата и основная программа очевидны.
Procedure Done;Begin
Init;
Solve;
Done;
End.
Вспомогательные процедуры
Function Eq(Const a, b: Real): Boolean;Procedure SwapInt(Var a, b: LongInt);
Var t: LongInt;
Begin
t:=a; a:=b; b:=t;
End;
Procedure Change(Const x: Real; Var rs: Real);
Var i, M: LongInt;
Begin
M:=0;FillChar(Oy,SizeOf(Oy),0);
FillChar(FOy,SizeOf(Foy),0);
For i:=1 To N Do
If Peres(i, x) Then Begin
{если есть пересечение?}
Oy[M+1]:=PrM[1,i].Y;Oy[M+2]:=PrM[2,i].Y;
{формируем массив ординат
для данной
координаты X}
FOy[M+1]:=1;FOy[M+2]:=-1;
{признаки начала и конца
отрезка}
Inc(M, 2);
End;
If M=0 Then rs:=0
Else Begin FstSort(Oy,FOy,1,M);
rs:=Abs(Calc(Oy,FOy,M));
End;
{сортируем Oy, переставляя
одновременно соответствующие
элементы массива FOy;
вычисляем новое значение длины
сечения – функция Calc}
End;
Разработка тестирующих систем для проведения олимпиады была выполнена студентами МГУ Матюхиным Виктором и Беровым Виталием. Они, а также студент СПбИТМО Пестов Олег являются авторами ряда задач.