Матч
237, Объединение прямоугольников (BoxUnion)
Дивизион 2, Уровень
2; Дивизион 1, Уровень 1
На плоскости задано множество
прямоугольников. Необходимо найти площадь их объединения. Например, площадь
объединения трех прямоугольников, заданных в 4 тесте,
равна 35. Массив rectangles
содержит набор строк, каждая из которых имеет формат “Left Bottom Right Top”,
где (Left, Bottom) – координаты левого нижнего угла, а (Right, Top) – правого
верхнего.
Класс: BoxUnion
Метод: int
area(vector<string> rectangles)
Ограничения:
массив rectangles содержит от 1 до 3 элементов, все координаты вершин
изменяются от 0 до 20000 включительно.
Вход. Массив rectangles, содержащий координаты вершин прямоугольников.
Выход. Площадь объединения прямоугольников.
Пример входа
rectangles |
{"200 300 203 304"} |
{"0 500 20000 501", "500 0 501 20000"} |
{"4 6 18 24", "7 2 12 19", "0 0 100 100"} |
{"1 3 5 6", "3 1 7 5", "4 4 9 7"} |
Пример выхода
12
39999
10000
35
РЕШЕНИЕ
геометрия
Поскольку прямоугольников не
более трех, воспользуемся принципом включения – исключения. Если в условии
задачи прямоугольников меньше трех, то добавим фиктивные прямоугольники с
координатами (0, 0, 0, 0) так, чтобы их стало три. Координаты прямоугольников
храним в массиве rec.
Просуммируем площади
прямоугольников, вычтем из суммы площади пересечений всех пар прямоугольников и
прибавим площадь общей части всех трех прямоугольников.
Каждый прямоугольник представляем
в виде массива из четырех чисел (Left Bottom Right Top). Функция _area(rect) находит
площадь прямоугольника rect. Функция unite(i,
j) объединяет прямоугольники i и j.
Результатом объединения является прямоугольник. Если прямоугольник не является
правильным (в четверке (Left Bottom Right Top) имеет место неравенство Left
> Right или Bottom > Top), то его площадь будет равна нулю. Функция unite3(i, j,
k) находит общую часть прямоугольников
i, j и k.
ПРОГРАММА
#include <cstdio>
#include <vector>
#include <string>
using namespace std;
vector<int>
temp(4);
vector<vector<int> > rec(3,temp);
int _area(vector<int>
rect)
{
if ((rect[2] <= rect[0]) || (rect[3] <=
rect[1])) return 0;
return (rect[2] - rect[0]) * (rect[3] - rect[1]);
}
vector<int>
unite(vector<int> i, vector<int> j)
{
vector<int> res(4);
res[2] = min(i[2],j[2]);
res[0] = max(i[0],j[0]);
res[3] = min(i[3],j[3]);
res[1] = max(i[1],j[1]);
return res;
}
vector<int>
unite3(vector<int> i, vector<int> j, vector<int>
k)
{
return unite(unite(i,j),k);
}
class BoxUnion
{
public:
int area(vector<string> rectangles)
{
int i, res;
for(i = 0; i < rectangles.size();
i++)
sscanf(rectangles[i].c_str(),
"%d %d %d %d",&temp[0],&temp[1],&temp[2],&temp[3]),
rec[i] = temp;
res = _area(rec[0]) + _area(rec[1]) + _area(rec[2]);
res = res - _area(unite(rec[0],rec[1])) - _area(unite(rec[1],rec[2])) –
_area(unite(rec[0],rec[2]));
res += _area(unite3(rec[0],rec[1],rec[2]));
return
res;
}
};