Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Программирование на C / C++


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты по данной тематике

Асмик Гаряка
Статус: Советник
Рейтинг: 11002
∙ повысить рейтинг »
Коцюрбенко Алексей aka Жерар
Статус: Советник
Рейтинг: 3995
∙ повысить рейтинг »
CradleA
Статус: Бакалавр
Рейтинг: 2050
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / C/C++

Номер выпуска:1783
Дата выхода:27.03.2013, 17:30
Администратор рассылки:Киселёва Алёна aka Verena (Академик)
Подписчиков / экспертов:87 / 65
Вопросов / ответов:1 / 1

Консультация # 187223: Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: Требуется решить задачу,такого рода: Строительная компания приобрела участок земли - прямоугольное поле размером N * M сек- торов. После проведения геологических исследований выяснилось, что на поле есть K непригодных для строительства секторов. Необходимо построи...


Консультация # 187223:

Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:
Требуется решить задачу,такого рода:
Строительная компания приобрела участок земли - прямоугольное поле размером N * M сек-
торов. После проведения геологических исследований выяснилось, что на поле есть K непригодных
для строительства секторов. Необходимо построить одно здание прямоугольной формы со сторо-
нами параллельными границам участка. Компания заинтересована в рациональном использовании
участка, поэтому границы здания должны упираться либо в непригодные для строительства секто-
ры, либо в границы участка. Сколько существует вариантов выбора места для строительства здания
на приобретенном участке?
Формат входного файла
В первой строке задаются размеры поля N, M (1 ≤ N, M ≤ 10^9) и количество непригодных
для строительства секторов K (1 ≤ K ≤ 500). В следующих K строках задаются координаты
непригодных секторов Xi, Yi (1 ≤ Xi & #8804; N, 1 ≤ Yi ≤ M). Все числа во входных данных целые.
Формат выходного файла
Число вариантов выбора места для строительства здания.



P.S.
Имя входного файла stdin
Имя выходного stdout
Пример
на входе
3 4 2
2 3
3 2
результат
5

Среда разработки = консольное приложение,желательно turbo C++

Дата отправки: 24.03.2013, 16:48
Вопрос задал: Иванов Д.И. (Посетитель)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Александр Чекменёв (Профессор):

Здравствуйте, Иванов Д.И.!

Идея -- если есть набор прямоугольников и оказалось, что надо добавить ещё одно препятствие, надо разбить те прямоугольники, в которые оно попадает. В общем, в этом алгоритм и состоит: иметь список прямоугольников(начать с одного прямоугольника NxM) и, считывая очередное препятствие(их хранить не надо), разбивать те прямоугольники, в которые оно попадает. Есть, правда, нюанс -- добавленный прямоугольник может целиком содержаться в другом. Поэтому, в самом конце просто за n^2 почистим список прямоугольников.

Код :
#include <iostream>
#include <list>

typedef unsigned long Int;

class Point
{
public:
    Int x;
    Int y;

    Point(Int _x, Int _y) : x(_x), y(_y) {}

    /*friend std::ostream & operator << ( std::ostream & os, const Point & p )
    {
        os << "(" << p.x << "," << p.y << ")";
        return os;
    }*/
};

class Rect
{
public:
    Point lt; // left top
    Point rb; // right bottom

    Rect(const Point & _lt, const Point & _rb) : lt(_lt), rb(_rb) {}

    /*friend std::ostream & operator << ( std::ostream & os, const Rect & r )
    {
        os << "[" << r.lt << ", " << r.rb << "]";
        return os;
    }*/
};

bool inbetween(Int x, Int a, Int b)
{
    return a <= x && x <= b;
}

bool pointInRect(const Point & p, const Rect & r)
{
    return inbetween(p.x, r.lt.x, r.rb.x)
        && inbetween(p.y, r.lt.y, r.rb.y);
}

// точка должна лежать внутри прямоугольника
std::list<Rect> breakRect(const Rect & r, const Point & p)
{
    std::list<Rect> rs;

    // если есть место слева
    if (p.x > r.lt.x) rs.push_back(Rect(r.lt, Point(p.x-1, r.rb.y)));
    // справа
    if (p.x < r.rb.x) rs.push_back(Rect(Point(p.x+1, r.lt.y), r.rb));

    // если есть место сверху
    if (p.y > r.lt.y) rs.push_back(Rect(r.lt, Point(r.rb.x, p.y-1)));
    // снизу
    if (p.y < r.rb.y) rs.push_back(Rect(Point(r.lt.x, p.y+1), r.rb));

    return rs;
}

// лежит ли первый прямоугольник во втором
bool into(const Rect & r, const Rect & big)
{
    return pointInRect(r.lt, big)
        && pointInRect(r.rb, big);
}

/*void printRects(const std::list<Rect> & rs)
{
    std::list<Rect>::const_iterator it = rs.cbegin();
    while (it != rs.cend())
    {
        std::cout << *it++ << std::endl;
    }

    std::cout << std::endl;
}*/

int main()
{
    Int N, M, K;
    std::cin >> N >> M >> K;

    // список прямоугольников
    std::list<Rect> rs;
    // вначале есть прямоугольник во всё поле
    rs.push_back(Rect(Point(1,1), Point(N,M)));

    //printRects(rs);

    for (Int i = 0; i < K; ++i)
    {
        // препятствие
        Int x, y;
        std::cin >> x >> y;
        Point p(x, y);

        // смотрим, не надо ли разбить что-то из имеющихся прямоугольников
        std::list<Rect>::iterator it = rs.begin();
        while (it != rs.end())
        {
            Rect r = *it; // текущий прямоугольник
            // если точка внутри прямоугольника -- надо бить
            if (pointInRect(p, r))
            {
                std::list<Rect> broken = breakRect(r, p);
                rs.splice(it, broken);

                rs.erase(it++);
            }
            else
            {
                ++it;
            }
        }

        //printRects(rs);
    }

    // чистим список прямоугольников от прямоугольничков, содержащихся в больших
    std::list<Rect>::iterator itBig = rs.begin();
    while (itBig != rs.end())
    {
        Rect big = *itBig; // прямоугольник, в который будем пытаться вмещать остальные

        std::list<Rect>::iterator it = rs.begin();
        while (it != rs.end())
        {
            // сам с собой проверять нечего
            if (it == itBig)
            {
                ++it;
                continue;
            }

            Rect r = *it; // прямоугольник, который постараемся выкинуть, как слишком маленький
            if (into(r, big))
                rs.erase(it++);
            else
                ++it;
        }

        ++itBig;
    }

    std::cout << rs.size() << std::endl;

    //printRects(rs);
}

Консультировал: Александр Чекменёв (Профессор)
Дата отправки: 25.03.2013, 03:27
Рейтинг ответа:

НЕ одобряю 0 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка  |  восстановить логин/пароль

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!



В избранное