Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Visual С++] Найти точки, лежащие на одной прямой 
V
    Опции темы
Ambition
Дата 12.10.2006, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Привет, народ. Подскажите кодик задачки   smile 
Условие задания:
На плоскасти заданы своими целочисленными координатами n точек. Найти всевозможные группы по 3,4,... точки, лежащие на одной прямой.
PM MAIL   Вверх
ivashkanet
Дата 12.10.2006, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 9
Всего: 149



Ambition, я представляю себе только пербор (ну с незначительными модификациями)  smile . 
Если надо, могу накатать.

P.S. А VS --- это какой язык?
PM MAIL WWW ICQ   Вверх
Ambition
Дата 12.10.2006, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Visual Studio (C++)
PM MAIL   Вверх
ivashkanet
Дата 12.10.2006, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 9
Всего: 149



Ambition, могу алгоритм перебора наклепать для VS (C#) потом "обработаешь напильником" пойдет?
PM MAIL WWW ICQ   Вверх
Ambition
Дата 12.10.2006, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



ок, пойдёт
PM MAIL   Вверх
ivashkanet
Дата 12.10.2006, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 9
Всего: 149



Наклепал.

Код

  class Program
    {
        struct Dot
        {
            public float X;
            public float Y;
            public Dot(float x, float y)
            {
                this.X = x;
                this.Y = y;
            }
        }

        static void Main(string[] args)
        {
            Dot[] dots = new Dot[10];
            dots[0] = new Dot(0, 0);
            dots[1] = new Dot(1, 2);
            dots[2] = new Dot(3, 4);
            dots[3] = new Dot(2, 4);
            dots[4] = new Dot(15, 20);
            dots[5] = new Dot(4, 36);
            dots[6] = new Dot(4, 11);
            dots[7] = new Dot(22, 19);
            dots[8] = new Dot(16, 32);
            dots[9] = new Dot(-56, -356);

            findDotsOnLine(dots);

            System.Console.ReadKey();
        }

        private static void findDotsOnLine(Dot[] dots)
        {
            int dotsCount = dots.Length;

            for (int i = 0; i < dotsCount; i++)
            {
                Dot startLineDot = dots[i];

                for (int j = i + 1; j < dotsCount; j++)
                {
                    // У прямой есть направляющий вектор (a, b) если по точкам, то 
                    // Если у двух прямых направляющие векторы совпадают (по направлению)
                    // то прямые паралельны, но в нашем случае они выходят из одной 
                    // точки (startLineDot) и поэтому обязаны совпасть,
                    // а значит третья точка лежит на одной прямой с первыми двумя
                    // так как нам важно только направление, то будем проверять условие
                    // a1 * b2 - b1 *a2 = 0

                    // Тута будем складывать точки лежащие на одной прямой с 
                    // i-ой и j-ой точками
                    Dot[] foundedDots = new Dot[dotsCount];
                    int foundedDotsCounter = 0;

                    float a1 = dots[j].X - startLineDot.X;
                    float b1 = dots[j].Y - startLineDot.Y;

                    for (int k = j + 1; k < dotsCount; k++)
                    {
                        float a2 = dots[k].X - startLineDot.X;
                        float b2 = dots[k].Y - startLineDot.Y;

                        if (a1 * b2 - b1 * a2 == 0)
                        {
                            // точка наша, добавляем ее в массив найденных
                            foundedDots[foundedDotsCounter] = dots[k];
                            foundedDotsCounter += 1;
                        }
                    }

                    // Если мы нашли хоть одну "третью" точку --- показываем массив точек
                    if (foundedDotsCounter > 0)
                    {
                        System.Console.Write("({0}, {1}), ", dots[i].X, dots[i].Y);
                        System.Console.Write("({0}, {1}), ", dots[j].X, dots[j].Y);

                        for (int l = 0; l < foundedDotsCounter; l++)
                        {
                            System.Console.Write("({0}, {1}), ", foundedDots[l].X, foundedDots[l].Y);
                        }
                        System.Console.WriteLine();
                    }
                }
            }
        }
    }


Правда есть маленький (но очень неприятный) недостаток.
Если у нас есть более четырех точек заведомо лежащих на одной прямой, то они появятся более чем один раз  smile 
Было бы неплохо удалять их, но массив не позволяет это делать. Может в С++ есть что-нибудь типа коллекций? Тогда было бы лучше smile

P.S. Пока буду помечать их (ставить в заведомо "невозможное значение" либо завести в структуре Dot флаг  smile  Не знаю)

Добавлено @ 15:01 
Вот так лучше, но некрасивее smile smile
Код

   class Program
    {
        struct Dot
        {
            public float X;
            public float Y;
            public Dot(float x, float y)
            {
                this.X = x;
                this.Y = y;
            }
        }

        static void Main(string[] args)
        {
            Dot[] dots = new Dot[10];
            dots[0] = new Dot(0, 0);
            dots[1] = new Dot(1, 2);
            dots[2] = new Dot(3, 4);
            dots[3] = new Dot(2, 4);
            dots[4] = new Dot(15, 20);
            dots[5] = new Dot(4, 36);
            dots[6] = new Dot(4, 11);
            dots[7] = new Dot(22, 19);
            dots[8] = new Dot(16, 32);
            dots[9] = new Dot(-56, -356);

            findDotsOnLine(dots);

            System.Console.ReadKey();
        }

        private static void findDotsOnLine(Dot[] dots)
        {
            Dot impossibleDot = new Dot(float.MinValue, float.MaxValue);

            int dotsCount = dots.Length;

            for (int i = 0; i < dotsCount; i++)
            {
                if (dots[i].X == impossibleDot.X && dots[i].Y == impossibleDot.Y) continue;

                Dot startLineDot = dots[i];

                for (int j = i + 1; j < dotsCount; j++)
                {
                    if (dots[j].X == impossibleDot.X && dots[j].Y == impossibleDot.Y) continue;

                    // У прямой есть направляющий вектор (a, b) если по точкам, то 
                    // Если у двух прямых направляющие векторы совпадают (по направлению)
                    // то прямые паралельны, но в нашем случае они выходят из одной 
                    // точки (startLineDot) и поэтому обязаны совпасть,
                    // а значит третья точка лежит на одной прямой с первыми двумя
                    // так как нам важно только направление, то будем проверять условие
                    // a1 * b2 - b1 *a2 = 0

                    // Тута будем складывать точки лежащие на одной прямой с 
                    // i-ой и j-ой точками
                    Dot[] foundedDots = new Dot[dotsCount];
                    int foundedDotsCounter = 0;

                    float a1 = dots[j].X - startLineDot.X;
                    float b1 = dots[j].Y - startLineDot.Y;

                    for (int k = j + 1; k < dotsCount; k++)
                    {
                        if (dots[k].X == impossibleDot.X && dots[k].Y == impossibleDot.Y) continue;

                        float a2 = dots[k].X - startLineDot.X;
                        float b2 = dots[k].Y - startLineDot.Y;

                        if (a1 * b2 - b1 * a2 == 0)
                        {
                            // точка наша, добавляем ее в массив найденных
                            foundedDots[foundedDotsCounter] = dots[k];
                            foundedDotsCounter += 1;
                            // помечаем ее
                            dots[k] = impossibleDot;
                        }
                    }

                    // Если мы нашли хоть одну "третью" точку --- показываем массив точек
                    if (foundedDotsCounter > 0)
                    {
                        System.Console.Write("({0}, {1}), ", dots[i].X, dots[i].Y);
                        System.Console.Write("({0}, {1}), ", dots[j].X, dots[j].Y);

                        for (int l = 0; l < foundedDotsCounter; l++)
                        {
                            System.Console.Write("({0}, {1}), ", foundedDots[l].X, foundedDots[l].Y);
                        }
                        System.Console.WriteLine();
                    }
                }
            }
        }
    }

PM MAIL WWW ICQ   Вверх
ivashkanet
Дата 12.10.2006, 15:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 9
Всего: 149



И еще: из за особенностей работы с числами с плавающей точкой (и не только) проверку на ноль лучше заменить на:

Код

System.Math.Abs( a1 * b2 - b1 * a2) < .0001

PM MAIL WWW ICQ   Вверх
Ambition
Дата 12.10.2006, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



спасибо
PM MAIL   Вверх
ivashkanet
Дата 12.10.2006, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 9
Всего: 149



Цитата(Ambition @  12.10.2006,  16:17 Найти цитируемый пост)
спасибо

Не за что  smile 
P.S. Ambition, пометь тему решенной.
PM MAIL WWW ICQ   Вверх
Ambition
Дата 12.10.2006, 17:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



сори, ок
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

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

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


 




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


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

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