Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.12.2012, 11:03   #1
FleXt
Пользователь
 
Регистрация: 01.12.2012
Сообщений: 28
По умолчанию Геометрия Си/С++

Из заданного множества точек на плоскости выбрать две различные точки так, чтобы количества точек, лежащих по разные стороны прямой, проходящей через эти точка, различались наименьшим образом.
Точки заданы координатами. Единственное что смог придумать это перебирать все пары точек, но это по времени получается достаточно долго.
FleXt вне форума Ответить с цитированием
Старый 01.12.2012, 13:51   #2
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
Точки заданы координатами. Единственное что смог придумать это перебирать все пары точек, но это по времени получается достаточно долго.
Перебирать все пары и для каждой пары "в лоб" перебирать все остальные точки и определять, по какую сторону от прямой они легли - в худшем случае O(N^3). Многовато, но не так чтобы отвратительно. По идее, если только кто-то не выпрыгнул из своей шкуры, пытаясь расставить точки так, чтобы на всякой прямой было не меньше трёх, разность 0 или 1 мы получим достаточно рано.
Оптимизация: берём точку и все остальные точки загоняем в массив, дополняя каждую углом на неё из выбранной. Сортируем массив по углам. Теперь для каждой точки определение разности количества точек с одной и с другой стороны занимает логарифмическое время, всего в худшем случае O(N^2*lnN). Для чётного числа точек минимум 0 в среднем случае должен достигаться уже на первой-второй точке, что сокращает среднее время до O(N*lnN).
Для нечётного числа точек всё хуже: вполне может быть единственная тройка точек, лежащая на одной прямой, разделяющей все остальные точки на две равномощные группы. В этом случае ничего умнее полного перебора мне в голову не приходит.
А вот для чётного числа точек есть вторая оптимизация: взять произвольное направление прямой; найти, перебрав все точки, какая прямая с таким направлением делит множество точек пополам; если она неизбежно проводится по точкам и число этих точек нечётно - взять другое произвольное направление и повторить; если она может быть не проведена ни через одну точку - дальше попытаться чуть "подвинуть" или "довернуть" её. Если за несколько итераций этот алгоритм не срабатывает - значит, точки подобраны специально и очень аккуратно, рекомендуется возвращение к предыдущему алгоритму и полный перебор.
Abstraction вне форума Ответить с цитированием
Старый 01.12.2012, 15:25   #3
FleXt
Пользователь
 
Регистрация: 01.12.2012
Сообщений: 28
По умолчанию

Код:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define N 15


int main()
{   int i,j=0,k,n;
    int v, left, right, min;
    int x[N],y[N];
    int imn=0, jmn=0;
    scanf("%d", &n);
     for( i=0;i<n;i++)
        scanf("%d%d",&x[i],&y[i]);
     for(i=0;(i<n)&&(min!=0||min!=1);i++)
        {

         for(j=j+i;(j<n)&&(min!=0||min!=1);j++)
         {
             left=0;
             right=0;
            for(k=1;k<n;k++)
               {

                v=(x[j]-x[i])*(y[k]-y[i])-(y[j]-y[i])*(x[k]-x[i]);
                if(v>0) left++;
                else if(v<0) right++;
               }
            min=abs(left-right);
         }
         imn=i;
         jmn=j;
        }
       printf("%d %d  %d %d",x[imn],y[imn],x[jmn],y[jmn]) ;
}
попытался написать, но не работает, где-то выхожу за размеры массива
FleXt вне форума Ответить с цитированием
Старый 01.12.2012, 15:30   #4
FleXt
Пользователь
 
Регистрация: 01.12.2012
Сообщений: 28
По умолчанию

да и точка находится не правильная)
FleXt вне форума Ответить с цитированием
Старый 01.12.2012, 15:44   #5
FleXt
Пользователь
 
Регистрация: 01.12.2012
Сообщений: 28
По умолчанию

Код:
     min=abs(left-right);
         }
         imn=i;
         jmn=j;
        }
вот тут ошибку нашел ,заменил на
Код:
 min=abs(left-right);
            imn=i;
           jmn=j;
         }

        }
но проблема осталась, ответ не правильный
FleXt вне форума Ответить с цитированием
Старый 03.12.2012, 12:56   #6
FleXt
Пользователь
 
Регистрация: 01.12.2012
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Abstraction Посмотреть сообщение
Перебирать все пары и для каждой пары "в лоб" перебирать все остальные точки и определять, по какую сторону от прямой они легли - в худшем случае O(N^3). Многовато, но не так чтобы отвратительно. По идее, если только кто-то не выпрыгнул из своей шкуры, пытаясь расставить точки так, чтобы на всякой прямой было не меньше трёх, разность 0 или 1 мы получим достаточно рано.
Оптимизация: берём точку и все остальные точки загоняем в массив, дополняя каждую углом на неё из выбранной. Сортируем массив по углам. Теперь для каждой точки определение разности количества точек с одной и с другой стороны занимает логарифмическое время, всего в худшем случае O(N^2*lnN). Для чётного числа точек минимум 0 в среднем случае должен достигаться уже на первой-второй точке, что сокращает среднее время до O(N*lnN).
Для нечётного числа точек всё хуже: вполне может быть единственная тройка точек, лежащая на одной прямой, разделяющей все остальные точки на две равномощные группы. В этом случае ничего умнее полного перебора мне в голову не приходит.
А вот для чётного числа точек есть вторая оптимизация: взять произвольное направление прямой; найти, перебрав все точки, какая прямая с таким направлением делит множество точек пополам; если она неизбежно проводится по точкам и число этих точек нечётно - взять другое произвольное направление и повторить; если она может быть не проведена ни через одну точку - дальше попытаться чуть "подвинуть" или "довернуть" её. Если за несколько итераций этот алгоритм не срабатывает - значит, точки подобраны специально и очень аккуратно, рекомендуется возвращение к предыдущему алгоритму и полный перебор.
Не могли бы Вы посмотреть мой код?
FleXt вне форума Ответить с цитированием
Старый 03.12.2012, 15:50   #7
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
for(j=j+i
Это почему и зачем?
Почему переменные целочисленные и подумали ли Вы про округление?
Что за условие min!=1?
Почему K считается от 1?
И какие из этих проблем нельзя было обнаружить с помощью отладчика?..
Abstraction вне форума Ответить с цитированием
Старый 03.12.2012, 16:23   #8
FleXt
Пользователь
 
Регистрация: 01.12.2012
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Abstraction Посмотреть сообщение
Это почему и зачем?
Почему переменные целочисленные и подумали ли Вы про округление?
Что за условие min!=1?
Почему K считается от 1?
И какие из этих проблем нельзя было обнаружить с помощью отладчика?..
for(j=j+i тк фиксирую первую точку, смотрю пары с остальными точками. Про целочисленные переменные не подумал. min!=1 а разве это не будет минимальной разностью? Четное количество точек можно разделить пополам, нечетное либо так же пополам, либо с одной стороны будет на 1 точку больше чем с другой, от сюда условие не равенства 1. К надо считать от нуля?
FleXt вне форума Ответить с цитированием
Старый 03.12.2012, 17:41   #9
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
for(j=j+i тк фиксирую первую точку, смотрю пары с остальными точками.
К середине времени работы программы, j=5, i=12. Счёт j в цикле начнётся со значения 17. Я не в силах понять стоящей за этим логики.
Цитата:
min!=1 а разве это не будет минимальной разностью? Четное количество точек можно разделить пополам, нечетное либо так же пополам, либо с одной стороны будет на 1 точку больше чем с другой, от сюда условие не равенства 1.
*вырезано цензурой*
Цитата:
Для нечётного числа точек всё хуже: вполне может быть единственная тройка точек, лежащая на одной прямой, разделяющей все остальные точки на две равномощные группы. В этом случае ничего умнее полного перебора мне в голову не приходит.
Цитата:
К надо считать от нуля?
Отвечаем вопросом на вопрос? Не знаю... может надо, может не надо. Но Вы организовали цикл так, что k пробегает значения от 1 до n-1. Я интересуюсь: почему Вы приняли такое решение.

Последний раз редактировалось Abstraction; 04.12.2012 в 09:29.
Abstraction вне форума Ответить с цитированием
Старый 04.12.2012, 04:51   #10
FleXt
Пользователь
 
Регистрация: 01.12.2012
Сообщений: 28
По умолчанию

Цитата:
for(i=0;(i<n)&&(min!=0||min!=1);i++ )
{

for(j=i+1;(j<n)&&(min!=0||min!=1);j ++)
{
left=0;
right=0;
for(k=j+1;k<n;k++)
{

v=(x[j]-x[i])*(y[k]-y[i])-(y[j]-y[i])*(x[k]-x[i]);
if(v>0) left++;
else if(v<0) right++;
}
min=abs(left-right);
imn=i;
jmn=j;
}

}
сделал вот так
FleXt вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
геометрия novichokkk Помощь студентам 10 18.04.2012 18:36
Геометрия Pascal.t Паскаль, Turbo Pascal, PascalABC.NET 2 17.12.2010 00:13
Геометрия в Си rik_nel Общие вопросы C/C++ 5 14.12.2010 13:43
Геометрия zumm Свободное общение 3 07.07.2010 18:37
Си геометрия Денни Помощь студентам 11 05.03.2010 09:41