Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Прямоугольники на плоскости 
:(
    Опции темы
_Y_
Дата 15.1.2011, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1651
Регистрация: 27.11.2006

Репутация: 8
Всего: 34



Я бы делал несколько проще и итерационно в комбинации с Монте Карло. Примерно так (многое из этого было высказано в предидущих сообщениях, но вразбивку):

Сначала описываем минимизируемую функцию F. Например, разность площадей зазора над и под объектом плюс разность площадей зазора слева и справа от объекта. Еще будем считать величину 
S=F(1)+F(2)+...+F(n) т.е. суммировать минимизируемые функци для всех объектов.

Теперь начинаем телодвижения:
1. Находим периметр - внешний контур - прямоугольник, за который объекты вылезать не должны. Если найти его трудно - делаем прямоугольник с запасом.
2. Заполняем углы ближайшими к ним объектами.
3. Двигаем каждый объект в сторону ближней линии периметра; но не позволяем объектам наезжать друг на друга. Таким образом расставляем внешние объекты по периметру. Внутренние объекты можно вообще не двигать на этом шаге, но тогда нужно сначала определить какие внешние, а какие внутренние - алгоритм усложняется.
4. Присваиваем объектам степени свободы: объекты, находящиеся в углах, двигаться права не имеют; объекты, соприкасающиеся с горизонтальными линиями периметра могут двигаться только по оси X; объекты, соприкасающиеся с вертикальными линиями периметра могут двигаться только по оси Y. Остальные (внутренние) объекты могут двигаться по двум осям.
5. Инициализируем иттерационный процесс рассчитав S.
6. Последовательно двигаем каждый объект в рамках его степеней свободы оптимизируя функцию F.
7. Считаем новое значение S и сравниваем с предидущим значением. Если значение уменьшилось идем к шагу 6. Если значение увеличилось (ухудшилось) идем к шагу 8. Если не изменилось - к шагу 8 или 9 не важно.
8. Возвращаем пложения объектов на один шаг назад.
9. Случайным образом изменяем последовательность работы с объектами, т.е. случайным образом перемешиваем массив объектов, не меняя их положения на картинке. Это делается для изменения последовательности работы с объектами. Переходим к пункту 6.

Работу алгоритма завершаем когда пункт 9 пройден заданное количество раз.

Алгоритм этот написан умозрительно - писать программу некогда к сожалению. Поэтому не знаю - может Монте Карло и излишество.  Серьезнее всего надо подойти к определению функции F. Как оптимизировать белые кантики вокруг объектов лучше всего знают верстальщики газет - эти вопросы зрительного восприятия они изучили задолго до появления компов.

Это сообщение отредактировал(а) _Y_ - 15.1.2011, 12:13


--------------------
Я вот в этом поучаствовал: http://sbor-nik.appspot.com/kick.jsp?id=sbor5737960678883328 (на правах саморекламы:)
PM MAIL WWW   Вверх
миг
Дата 15.1.2011, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 15.9.2008

Репутация: нет
Всего: 1



_Y_, Согласен.. но я думаю в третьем шаге можно определить внешние объекты по координатам углов прямоугольника.. Мне пришло в голову сам ограничивающий прямоугольник рассматривать как двумерный массив.. А координаты реальных прямоугольников записать в виде координат массива i,j и двигать все это дело внутри массива.. Причем для экономии памяти сам массив создавать не обязательно. 
Вот! В С++ создал класс прямоугольник и храню там информацию о количестве прямоугольников и их вершинах.. 

 и планирую двигаться по виртуальному массиву с помощью двух циклов for(int i=0; i<n;i++), for(int j=0;j<m;j++)


 
Код

#include<malloc.h>
typedef struct tagPOINT
{
    long x;
    long y;
}POINT, *PPOINT;
struct Rectangle
{
    POINT point[4];
};

class rect_4
{
private:
    int pV;// ко-во прямоугольников
    int n_x,n_y;// для определения размера виртуального массива
    Rectangle* prim;
public:
    bool Shift_prm(int n, POINT p); // номер прямоугольника и точка до которой сдвигать
    void initial();// для каждого прямоугольника вводим координаты i,j
    rect_4(int);// начальная инициализация класса
//    void vv();
    bool _if(int,int,int &n);// если точка попадает в прямоугольник то в какой?
};

rect_4::rect_4(int p)
{
    n_x=0;
    n_y=0;
    pV=p;
    prim=(Rectangle*)malloc(p*sizeof(Rectangle));
}

// X и Y целые не отрицательные числа
// i - номер прямоугольника
// n - номер точки в прямоугольнике
// вершины прямоугольника для простоты кода нужно вводить в определенной последовательности

//
//    1.______.2
//     |            |
//     |            |
//     .______.
//    0            3
void rect_4::initial()
{
    for(register int i=0; i<pV;i++)
    {
        int x,y;
        cout<< "Vvod "<<i+1<<" rectangle"<<endl;
        for(register int n=0;n<4;n++){
            cout<<"Vvedite koord X to4ki "<<(n+1)<<" (gde X tceloe 4islo X>=0): ";
            cin>>    prim[i].point[n].x;
            cout<<endl;
            cout<<"Vvedite koord Y to4ki "<<(n+1)<<" (gde Y tceloe 4islo Y>=0): ";
            cin>>prim[i].point[n].y;
            if(prim[i].point[n].x>n_x)n_x=prim[i].point[n].x;
            if(prim[i].point[n].y>n_y)n_y=prim[i].point[n].y;
        }
    }
}

//проверка условия
//попадает ли точка в прямоугольник
//
//    1.______.2
//     |            |
//     |            |
//     .______.
//    0           3
//
// i - номер прямоугольника
// 
bool rect_4::_if(int x,int y, int &n)
{
    n=0;
    for(register int i=0; i<pV;i++)
    {
        if(x>prim[i].point[0].x && x<prim[i].point[3].x)
        {
            if(x>prim[i].point[1].x && x<prim[i].point[2].x)
            {
                n=i;
                return true;
            }
        }
    }
    return false;
}


//первый параметр номер прямоугольника второй точка до которой сдвигаем прямоугольник

bool rect_4::Shift_prm(int n, POINT p)
{
// определить в какую сторону сдвигать..
// организовать цикл сдвига прямоугольников по клеткам до нужной точки
// проверить не пересекает ли прямоугольник другие если да то сдвиг остановить.
 
    int temp;
    if(prim[n].point[0].x<p.x){
        //             _____    сдвиг в лево
        // точка  |        |
        //             |____|
        for(register int i=prim[n].point[0].x;i<=p.x;i++)//ñäâèãàåì
        {
            for(register int k=prim[n].point[1].y;k<=p.y;k++){
                if(_if(i,k,&temp){
                    k=p.y;
                    i=p.x;
                }
                else{
                    for(register int j=0;j<4;j++)
                    {
                        prim[n].point[j].x=i;
                    }
                }
            }
        }
    }
    else{
        if(prim[n].point[2].x>p.x)
        {
        //         _____   сдвиг вправо 
        //        |          |  точка
        //        |_____|
            for(register int i=p.x;i<=prim[n].point[2].x;i++)
            {
            }
        }
    }

    if(prim[n].point[1].y<p.y){
        //         òî÷êà
        //         _____    
        //        |         |
        //        |_____|
        for()//ñäâèãàåì
    }
    else{
        if(prim[n].point[0].y>p.y)
        {
        //         _____    
        //        |     |
        //        |_____|
        //         òî÷êà
        }
    }
    return true;
}


это я на работе в обеденный перерыв пытался набацать. правда я еще не доделал, но на мой взгляд должно выглядеть как то так))



Это сообщение отредактировал(а) миг - 15.1.2011, 14:04
--------------------
Oaks may fall when reeds stand the storm.
PM MAIL   Вверх
_Y_
Дата 15.1.2011, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1651
Регистрация: 27.11.2006

Репутация: 8
Всего: 34



миг, в C++ я, к сожалению, не силен. Что касается пункта 3, то я описал сам принцип. А то что каждый пункт можно реализовать по-разному очевидно.

 Кстати, на практике придется еще и задать приоритет направлений в третьем пункте. Например, если объект занимает всю длину или высоту (как нижний объект на последних картинках), то двигать его надо к левой границе или к правой границе или ставить по центру. Это правило должно быть задано априори.

ИМХО самое сложное все-таки минимизируемая функция.


--------------------
Я вот в этом поучаствовал: http://sbor-nik.appspot.com/kick.jsp?id=sbor5737960678883328 (на правах саморекламы:)
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.1384 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.