Задача о красных и синих точках

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

Государственное образовательное учреждение высшего профессионального образования

«Санкт-Петербургский государственный политехнический университет»

Институт менеджмента и информационных технологий

Санкт-Петербургского государственного политехнического университета в г.Череповце


КУРСОВОЙ ПРОЕКТ

Дисциплина: Высокоуровневые методы информатики и программирования

Тема: Задача о красных и синих точках


Специальность: 080801 Прикладная информатика (в экономике)

Выполнил студент гр. О.581 Марунова Ю.Д.,

Никитин А.Ю.


2009 год

Содержание


1.Введение

. Теоретическая часть

.1 Техническое задание

.2 Характеристика программы

. Практическая часть

.1 Структура программы

.2 Описание используемых типов данных

.3 Описание основных алгоритмов

.Резюме

.1 Выводы

.2 Возможные модернизации

. Литература

. Приложение

.1 Текст программы


1. Введение


Целью данного курсового проекта является разработка программы для решения задачи о синих и красных точках. Суть задачи заключается в построении отрезков на плоскости, на которой расположены синие и красные точки, являющиеся концами этих отрезков. Причём сумма длин этих отрезков должна быть минимальна.

В курсовом проекте планируется разработать техническое задание на разработку, построение структурной схемы и блок-схемы разрабатываемого автоматического и ручного алгоритма.

2. Теоретическая часть


.1 Техническое задание


.Введение.

Программа предназначена для определения возможности построения n отрезков с разноцветными концами, суммарная длина которых будет минимальна (из точки может выходить только один отрезок).

. Основание для разработки.

Выполнение курсовой работы по дисциплине «Высокоуровневые методы информатики и программирования ».

. Назначение разработки.

Данная программа создана в опытных целях для проверки возможности оптимального варианта построения отрезков.

. Требования к программе.

.1. Требования к функциональным характеристикам.

В состав программы входят функции

построить n отрезков.

Входные данные - указание размеров a и n.

Выходные данные - графическая информация, выводимая на экран.

.2. Требования к надежности.

Надежное функционирование программы обеспечивается за счёт ограниченного множества функций программы.

.3. Требования к составу и параметрам технических средств ЭВМ, внешние устройства, их характеристики.

Для функционирования программы требуется компьютер со следующими минимальными требованиями:

CPU -8086

RAM-640 KB

VGA- монитор

Прочие внешние устройства для работы программы не требуются.

.4. Требования к информационной и программной совместимости ОС, система программирования, используемые программные средства, методы решения, информационные структуры и т.п.

Для функционирования программы требуется ОС MS-DOS версии 3.30 или выше, от 64 килобайт свободной оперативной памяти. Программа разработана в интегрированной среде Borland Delphi версии 7.0.

. Требования к программной документации.

Пояснительная записка, техническое задание, руководство пользователя.

. Технико-экономические показатели. Ориентировочная экономическая эффективность, преимущества по сравнению с аналогами.

. Стадии и этапы работ (примерный план)


Стадии и этапы работСодержание работСрокиИсполнителиТЗПостановка задачи, определение требований, структуры данных, метода решения и т.д.20.04.2009Марунова Ю.Д.Технический проектРазработка алгоритма, определение формы представления данных, структуры программы. Проектирование интерфейса Пояснительная записка.20.05.2009Марунова Ю.Д.Рабочий проектПрограммирование и реализация В том числе - Реализация интерфейса - Реализация основных графических функций - Реализация остальных функций - Испытание и тестирование программы. - Разработка документации.27.05.2009Марунова Ю.Д.Защита проектаЗавершение пояснительной записки Получение допуска к защитеНе позднее, чем за 2 дня до даты защитыМарунова Ю.Д.2.2 Характеристика программы


Для удобства использования программы, она должна иметь интуитивно понятный интерфейс. Насколько это возможно здесь эта цель достигнута. При необходимости пользователь может обратиться к справке, но работа программы довольно проста. При запуске всего лишь необходимо накидать мышкой на поле синие и красные точки и сделать расчёты либо в автоматическом режиме, либо в ручном.


.3 Общий вид программы


Программа, рассчитывающая минимальную суммарную длину отрезков с концами разного цвета, выглядит следующим образом:

·Большое поле (В нем пользователь определяет местоположение точек. После введения равного количества точек 2 цветов здесь эти точки соединяются таким образом, что отрезок получается с концами разных цветов. А сумма этих отрезков минимальна )

·Определение количества точек, введенных пользователем с описанием их цвета.

·3 режима, выбираемых пользователем:

1.Режим ввода красных точек, предназначенный для определения пользователем местоположения красных точек на чистом поле. При данном процессе после щелчка мыши на поле появляется красная точка.

2.Режим ввода синих точек, предназначенный для определения пользователем местоположения синих точек на чистом поле. При данном процессе после щелчка мыши на поле появляется синяя точка.

.Ручной режим. Данный режим позволяет пользователю самому как ввести точки так и провести между ними отрезок с разными концами соответственно.

·Кнопка «Очистить» (Полностью очищает оба поля от точек и их координат, а так же сбрасывает счетчики количества точек.)

·Кнопка «Рассчитать» (Даная кнопка действует только после ввода равного количества точек 2 цветов. После ее нажатия программа расчерчивает такие отрезки с концами разных цветов, сумма которых минимальна. Ниже Малого поля компьютер показывает размер этой суммы.)

·Кнопка «Шаг». При каждом ее нажатии программа показывает и рассчитывает разные варианты соединения точек.


.4 Алгоритм работы с программой


Данный алгоритм является некой инструкцией для пользования программой, рассчитывающей минимальную сумму отрезков с концами разных цветов.

1.Выбираем один из режимов ввода точек: Режим ввода красных

точек / Режим ввода синих точек.

2.Расставляем в произвольном порядке на Большом поле точки

определенного цвета.

3.Меняем режим на ввод точек следующего цвета и так же расставляем

их на поле в совершенно произвольном порядке.

. Выбираем ручной или автоматический режим работы.

. Количество точек разных цветов должно быть одинаковым. В ином случае кнопка «Рассчитать» не активируется.

6.При выполнении условия из пункта №5, активируется кнопка «Рассчитать». Теперь, при ее нажатии, на Большом поле появляются вышеописанные отрезки, а ниже высвечивается их min сумма.

7.Теперь, после получения окончательного результата, пользователь может очистить Большое и Малое поля с помощью кнопки «Очистить».

.После того, как пользователь расставил все точки, при каждом нажатии кнопки «Шаг» программа показывает и рассчитывает новые варианты соединения точек.

.Еще один, ручной режим, пользователь реализует соответственно сам. То есть, после того, как пользователь расставил все точки, при нажатии кнопки «Курсор» он может сам соединять точки в том порядке, в котором захочет, при этом в Малом поле автоматически отображается сумма получившихся отрезков. После отжатия этой же кнопки нужно нажать кнопку «Шаг» и тогда программа покажет правильный вариант, т.е. вариант с минимальной суммой отрезков.


.5 Некоторые особенности данной программы


a.Кнопка «Расчитать» загорается только при равном количестве точек обоих цветов. Это объясняется математически.

Вообще длина отрезка рассчитывается с помощью координат его концов, расположенных в координатной плоскости. Нулевым отрезок называется в том случае, если координаты его начала и конца совпадают. Если на поле есть одна лишняя точка, то теоретически, это нулевой отрезок. Но, напомню, что в нашем случае отрезок должен быть с концами разных цветов. Поэтому при наличии лишних точек программа не работает, т.к. не соблюдается одно из главных условий задачи.

b.Кнопкой «Очистить» можно воспользоваться в любой момент процесса выполнения алгоритма, что наиболее удобно для пользователя в случае какой-либо ошибки. Но очищается полностью все поле в любом из режимов.


2.6 Математическое обоснование


Для математического обоснования данной задачи мне потребуется изучение темы «Вектора» и соответственно основные формулы: «Длина вектора» или «Расстояние между 2 точками».

Задача(условно): Дано N точек синего цвета и N точек красного цвета, координаты их известны. Нужно соединить их так, чтобы расстояние от точки одного цвета до точки другого цвета было минимальным из возможных вариантов. Далее рассчитать сумму их длин.

Примечание: Если мы соединим точки вышеописанным образом, то при сложении длин получившихся отрезков у нас уже получается минимальная сумма длин этих отрезков.

Решение:.Нужно соединить точки разных цветов так , чтобы из всех возможных вариантов получившаяся длина была минимальной.

Для расчета длины используем формулу длины вектора:


A¯B = ?(x2 - x1)2 + (y2 - y1)2(1)

.После того, как выбраны нужные (минимальные) варианты длин отрезков, нужно просто суммировать эти длины, в результате, задача решена, получен нужный ответ.


3. Практическая часть


.1 Структура программы


Анализируя задание, мы разрабатываем структурную схему программы, которая будет содержать основные блоки, описание выполняемых ими функций и их местоположение в программе. Для программы решения задачи о красных и синих точках получим следующую структурную схему:



Рассмотрим некоторые блоки, встречающиеся в программе.

Интерфейс - этот блок осуществляет взаимодействие пользователя и программы. Взаимодействие осуществляется с помощью монитора, клавиатуры и мыши.

Ввод синих и красных точек- в этом блоке запоминаются данные о синих и красных точек и размещаются на поле пользователем.

Построение отрезков - блок, который производит построение отрезков из красных и синих точек.

Отображение хода работы алгоритма - в таблице отражаются отрезки и их суммарная длина.

Визуализация результатов - отображение изменений происходящих в программе.

Справка - производная интерфейса, служит для получения сведений по эксплуатации программы.


.2 Описание используемых типов данных


В ходе реализации программы использовались как стандартные структуры данных, так и собственные, созданные непосредственно при проектировании алгоритма.

Для хранения данных о красных и синих точках используется спиcок pList типа TList. Число точек хранится в переменной tCount, число красных точек - в redCount, число синих точек - в blueCount.

Также был создан тип данных TPnt для хранения структуры данных о точке имеющий следующий вид:


PPnt = ^TPnt;= record,Y: integer;: byte;: integer;: boolean;

end;

Как видно он основан на указателях (PPnt ссылается на адресное пространство типа TPnt), и использование этого типа подразумевает хранение следующей информации о точке:

·Координаты X и Y

·Цвет точки (1 - красный, 2 - синий)

·Связана ли точка (Linked = true/false)

·Номер точки, с которой связана данная точка, если она связана (num)


.3 Описание основных алгоритмов


В программе реализован автоматический алгоритм поиска отрезков, составляющих минимальную суммарную длину, и дальнейшее рассмотрение работы программы основано на этом основном алгоритме. Остальные алгоритмы, в том числе и ручной являются вспомогательными и необходимы лишь для отражения результатов и реализации пользовательского интерфейса.

Подробное описание автоматического и ручного алгоритмов было приведено ранее, в пункте 2.4.

Поиск минимальной суммы длин отрезков

Данная задача является классическим примером динамического программирования. Полный перебор, как легко доказать, требует экспоненциального времени, что для алгоритма не есть хорошо, применение же динамического программирования упрощает эту задачу и как далее будет видно сложность этого алгоритма есть O(x^3).

Изобразим работу алгоритма графически:

Рис. 1


Код процедуры, реализующей данный алгоритм:


procedure FindLines;,j,start: integer;,P2,PMin,Pz: PPnt;,Sum: double;start:= 0 to pList.Count-1 do:=0;.Clear;i:= 0 to pList.Count-1 do:= pList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;i:= start to tmpList.Count-2 do:= tmpList.Items[i];not P^.Linked then:= MaxInt;j := 0 to tmpList.Count - 1 doi<>j then:= tmpList.Items[j];(not P2^.Linked) and (P2^.rColor <> P^.rColor) thensqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y)) < Min then:= sqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y));:= P2;;;;:=Sum+Min;^.Linked := True;^.Linked := True;^.Num := P^.Num;;;i := 0 to start-1 do:= tmpList.Items[i];not P^.Linked then:= MaxInt;j := 0 to tmpList.Count - 1 doi<>j then:= tmpList.Items[j];(not P2^.Linked) and (P2^.rColor <> P^.rColor) thensqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y)) < Min then:= sqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y));:= P2;;;;:=Sum+Min;^.Linked := True;^.Linked := True;^.Num := P^.Num;;;start=0 then:=sum;.Clear;i:= 0 to tmpList.Count-1 do:= tmpList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;if sum<minsum then:=sum;.Clear;i:= 0 to tmpList.Count-1 do:= tmpList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;;;.Clear;i:= 0 to oList.Count-1 do:= oList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;.Label3.Caption := 'Минимальная сумма отрезков: ' + FloatToStr(minSum);

end;


Данный алгоритм содержит несколько циклов: один глобальный цикл и два вложенных, которые в свою очередь включают в себя ещё по одному вложенному циклу. Параметром для внешнего глобального цикла является переменная start, которая делит данный список как бы на два сегмента. Потом внутренние циклы последовательно перебирают переменные в первом и втором сегментах. Данные переменные берутся в предположении, что они являются началом отрезка, а концы отрезков перебираются ещё одним циклом по всему списку. В итоге складывается картина того, что начала отрезков берутся в разных сегментах, размеры которых меняются в процессе прогона глобального цикла, а концы - из всего списка. Данный способ перебора элементов позволяет перебрать все отрезки, выбрать из них минимальные и найти их минимальные суммы. Суммирование в предварительную минимальную сумму для каждого набора отрезков происходит, если расстояние от данной точки (начала отрезка) до перебираемой точки (конца отрезка) меньше, чем расстояния от данной точки до всех остальных. В итоге мы получаем суммы длин наборов отрезков, из которых запоминаем в свою очередь минимальную сумму.

Ниже приведена общая блок-схема алгоритма:



4. Резюме


.1 Выводы


В результате выполнения курсового проекта была создана программа решения задачи о красных и синих точках, которая вполне нормально работает, и сильных отклонений нет.

К достоинствам программы можно отнести:

- простой интерфейс без излишних сложностей;

процесс работы программы визуализируется;

К недостаткам можно отнести следующее:

- невозможность более детального анализа алгоритма;


.2 Возможные модернизации

программа задача алгоритм

1. Доработать программу и дать возможность пользователю более детального анализа алгоритма.

5. Литература


1. Т. Кормен, Ч. Лейзерсон, Р. Ривест «Алгоритмы: построение и анализ».

. В.В. Фаронов «Delphi - программирование на языке высокого уровня».

. Ю.С. Избачков, В.Н. Петров «Информационные системы», второе издание

6. Приложение


.1 Текст программы

Unit1;

interface, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,, ComCtrls, Menus, ToolWin, ExtCtrls, StdCtrls, ImgList, Grids,, ShellAPI;= class(TForm): TMainMenu;: TMenuItem;: TMenuItem;: TPanel;: TToolBar;: TToolButton;: TToolButton;: TImage;: TButton;: TButton;: TImageList;: TToolButton;: TMenuItem;: TMenuItem;: TScrollBox;: TImage;: TGroupBox;: TLabel;: TLabel;: TLabel;: TButton;: TStringGrid;: TPanel;ToolButton1Click(Sender: TObject);ToolButton3Click(Sender: TObject);FormCreate(Sender: TObject);Image1MouseUp(Sender: TObject; Button: TMouseButton;: TShiftState; X, Y: Integer);ToolButton2Click(Sender: TObject);Button1Click(Sender: TObject);Button2Click(Sender: TObject);Button3Click(Sender: TObject);N4Click(Sender: TObject);N3Click(Sender: TObject);

{ Private declarations }

{ Public declarations };= ^TPnt;= record,Y: integer;: byte;: integer;: boolean;;: TForm1;: byte;, tmpList, oList, rList: TList;, redCount, blueCount: integer;, cHeight: integer;: double;_sh: integer;_1, j_1, i_2, j_2: integer;,j, start: integer;,P2,PMin,Pz: PPnt;,Sum: double;,y: integer;:Boolean;_col,ip1,ip2:integer;

{$R *.dfm}ClearGrid;rRect: TRect;.Left := cWidth + 1;.Right := Form1.Image2.Width;.Top := 0;.Bottom := Form1.Image2.Height;.Image2.Canvas.Brush.Color := clWhite;.Image2.Canvas.FillRect(rREct);;FindLines;,j,start: integer;,P2,PMin,Pz: PPnt;,Sum: double;start:= 0 to pList.Count-1 do:=0;.Clear;i:= 0 to pList.Count-1 do:= pList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;i:= start to tmpList.Count-2 do:= tmpList.Items[i];not P^.Linked then:= MaxInt;j := 0 to tmpList.Count - 1 doi<>j then:= tmpList.Items[j];(not P2^.Linked) and (P2^.rColor <> P^.rColor) thensqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y)) < Min then:= sqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y));:= P2;;;;:=Sum+Min;^.Linked := True;^.Linked := True;^.Num := P^.Num;;;i := 0 to start-1 do:= tmpList.Items[i];not P^.Linked then:= MaxInt;j := 0 to tmpList.Count - 1 doi<>j then:= tmpList.Items[j];(not P2^.Linked) and (P2^.rColor <> P^.rColor) thensqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y)) < Min then:= sqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y));:= P2;;;;:=Sum+Min;^.Linked := True;^.Linked := True;^.Num := P^.Num;;;start=0 then:=sum;.Clear;i:= 0 to tmpList.Count-1 do:= tmpList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;if sum<minsum then:=sum;.Clear;i:= 0 to tmpList.Count-1 do:= tmpList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;;;.Clear;i:= 0 to oList.Count-1 do:= oList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;.Label3.Caption := 'Минимальная сумма отрезков: ' + FloatToStr(minSum);;DrawGrid(vList: TList);i,j: integer;: TRect;: PPnt;j:=1 to vList.Count do.Image2.Canvas.Pen.Color := clBlack;.Left := cWidth * j;.Top := 0;.Right := cWidth * (j+1);.Bottom := cHeight;.Image2.Canvas.FillRect(rRect);.Image2.Canvas.Brush.Color := clInactiveCaption;.Image2.Canvas.FillRect(rRect);.Image2.Canvas.Font.Style := [fsBold];.Image2.Canvas.TextOut(j * cWidth + round(cWidth/2)-3, 1, IntToStr(j));i:=0 to 5 do.Image2.Canvas.MoveTo(cWidth*j, i*cHeight);.Image2.Canvas.LineTo(cWidth*(j + 1), i*cHeight);;i:= j to j + 1 do.Image2.Canvas.MoveTo(i*cWidth,0);.Image2.Canvas.LineTo(i*cWidth,cHeight*5 + 1);;.Image2.Canvas.Font.Style := [];.Image2.Canvas.Brush.Color := clWhite;:= vList.Items[j-1];.Image2.Canvas.TextOut((j+1)*cWidth - round(cWidth/2) - 8, cHeight + 1, IntToStr(p^.X));.Image2.Canvas.TextOut((j+1)*cWidth - round(cWidth/2) - 8, 2*cHeight + 1, IntToStr(p^.Y));.Image2.Canvas.TextOut((j+1)*cWidth - round(cWidth/2) - 2, 3*cHeight + 1, IntToStr(p^.num));p^.rColor = 1 then.Left := cWidth * j + 1;.Top := cHeight * 4 + 1;.Right := cWidth * (j+1);.Bottom := cHeight*5;.Image2.Canvas.Brush.Color := clRed;.Image2.Canvas.FillRect(rRect);;p^.rColor = 2 then.Left := cWidth * j + 1;.Top := cHeight * 4 + 1;.Right := cWidth * (j+1);.Bottom := cHeight*5;.Image2.Canvas.Brush.Color := clBlue;.Image2.Canvas.FillRect(rRect);;;;DeletePoints(vList: TList);p: PPnt;vList.Count > 0 do:= vList.Items[0];(P);.Delete(0);;:= 0;:= 0;:= 0;;DrawPoints(vList: TList);i,j: integer;, p2: PPnt;i := 0 to vList.Count-1 do:= vList.Items[i];p^.rColor = 1 then.Image1.Canvas.Brush.Color := clRed;p^.rColor = 2 then.Image1.Canvas.Brush.Color := clBlue;.Image1.Canvas.Pen.Color := clBlack;.Image1.Canvas.Ellipse(p^.X-4,p^.Y-4,p^.X+4,p^.Y+4);.Image1.Canvas.Brush.Color := clWhite;.Image1.Canvas.TextOut(p^.X-20, p^.Y-5, IntToStr(i+1));j:=i+1 to vList.Count - 1 do:= vList.Items[j];p^.num = p2^.num then.Image1.Canvas.MoveTo(p^.X, p^.Y);p^.rColor = 1 then Form1.Image1.Canvas.Pen.Color := clRed;p^.rColor = 2 then Form1.Image1.Canvas.Pen.Color := clBlue;.Image1.Canvas.LineTo(round((P^.X+P2^.X)/2),round((P^.Y+P2^.Y)/2));p2^.rColor = 1 then Form1.Image1.Canvas.Pen.Color := clRed;p2^.rColor = 2 then Form1.Image1.Canvas.Pen.Color := clBlue;.Image1.Canvas.LineTo(P2^.X,P2^.Y);;;;;AddDrawPoint(vList: TList; X,Y: integer);p: PPnt;(tCount);.Image1.Canvas.Pen.Color := clBlack;rColor = 1 then(RedCount);.Image1.Canvas.Brush.Color := clRed;.Image1.Canvas.Ellipse(X-4,Y-4,X+4,Y+4);.Image1.Canvas.Brush.Color := clWhite;.Image1.Canvas.TextOut(X-20, Y-5, IntToStr(tCount));(p);^.X := X;^.Y := Y;^.rColor := 1;^.Linked := false;^.num := tCount;.Add(p);;rColor = 2 then(BlueCount);.Image1.Canvas.Brush.Color := clBlue;.Image1.Canvas.Ellipse(X-4,Y-4,X+4,Y+4);.Image1.Canvas.Brush.Color := clWhite;.Image1.Canvas.TextOut(X-20, Y-5, IntToStr(tCount));(p);^.X := X;^.Y := Y;^.rColor := 2;^.Linked := false;^.num := tCount;.Add(p);;;AddGridPoint(vList: TList);rRect: TRect;: integer;: PPnt;rColor = 0 then exit;:= 50;:= 15;.Left := cWidth * vList.Count;.Top := 0;.Right := cWidth * (vList.Count+1);.Bottom := cHeight;.Image2.Canvas.FillRect(rRect);.Image2.Canvas.Brush.Color := clInactiveCaption;.Image2.Canvas.FillRect(rRect);.Image2.Canvas.Font.Style := [fsBold];.Image2.Canvas.TextOut(vList.Count * cWidth + round(cWidth/2)-3, 1, IntToStr(vList.Count));i:=0 to 5 do.Image2.Canvas.MoveTo(cWidth*vList.Count, i*cHeight);.Image2.Canvas.LineTo(cWidth*(vList.Count + 1), i*cHeight);;i:= pList.Count to pList.Count + 1 do.Image2.Canvas.MoveTo(i*cWidth,0);.Image2.Canvas.LineTo(i*cWidth,cHeight*5 + 1);;.Image2.Canvas.Font.Style := [];.Image2.Canvas.Brush.Color := clWhite;:= vList.Items[vList.Count-1];.Image2.Canvas.TextOut((vList.Count+1)*cWidth - round(cWidth/2) - 8, cHeight + 1, IntToStr(p^.X));.Image2.Canvas.TextOut((vList.Count+1)*cWidth - round(cWidth/2) - 8, 2*cHeight + 1, IntToStr(p^.Y));

//if p^.Linked

//then.Image2.Canvas.TextOut((vList.Count+1)*cWidth - round(cWidth/2) - 2, 3*cHeight + 1, IntToStr(p^.num));

//else

//Form1.Image2.Canvas.TextOut((vList.Count+1)*cWidth - round(cWidth/2) - 2, 3*cHeight + 1, '-');p^.rColor = 1 then.Left := cWidth * vList.Count + 1;.Top := cHeight * 4 + 1;.Right := cWidth * (vList.Count+1);.Bottom := cHeight*5;.Image2.Canvas.Brush.Color := clRed;.Image2.Canvas.FillRect(rRect);;p^.rColor = 2 then.Left := cWidth * vList.Count + 1;.Top := cHeight * 4 + 1;.Right := cWidth * (vList.Count+1);.Bottom := cHeight*5;.Image2.Canvas.Brush.Color := clBlue;.Image2.Canvas.FillRect(rRect);;;pointsDraw;i: integer;: PPnt;.Image1.Canvas.Brush.Color := clWhite;.Image1.Canvas.FillRect(Form1.Image1.Canvas.ClipRect);.Image1.Canvas.Rectangle(Form1.Image1.Canvas.ClipRect);i:=0 to pList.Count - 1 do:= pList.Items[i];p^.rColor = 1 then.Image1.Canvas.Brush.Color := clRed;.Image1.Canvas.Ellipse(p^.X-4,p^.Y-4,p^.X+4,p^.Y+4);;p^.rColor = 2 then.Image1.Canvas.Brush.Color := clBlue;.Image1.Canvas.Ellipse(p^.X-4,p^.Y-4,p^.X+4,p^.Y+4);;;;TForm1.ToolButton1Click(Sender: TObject);.Cursor := crCross;:= 1;;TForm1.ToolButton3Click(Sender: TObject);

var i:Integer;(fl=false) then //кнопка нажата первый раз. включено ручное черчение

begin:=0;_col:=0;:=true;.Cursor := crCross;:= 0;.Enabled:=false;.Enabled:=false;:=1;.RowCount := 2; //отрисовка таблицы вывода результата.ColCount := round(pList.Count/2)+2;.Cells[StringGrid1.ColCount-1,0] := 'Сумма';

end//выход из режима черчения//возврат связей в исходное состояние

for i:= 0 to pList.Count-1 do(pList.Items[i])^.Linked:=false;:= 0;.Cursor := crDefault;:=false;.Enabled:=true;.Enabled:=true;;;TForm1.FormCreate(Sender: TObject);: TRect;: integer;

begin //пераоночальное присваивание переменных:=false;

start := 0;_1 := start_sh;_1 := 0;_2 := 0;_2 := 0;:= 0;:= 0;:= 0;:= 50;:= 15;.Left := 0;.Top := 0;.Right := Image1.Width;.Bottom := Image1.Height;.Canvas.FillRect(rRect);.Canvas.Rectangle(rREct);.Left := 0;.Top := 0;.Right := Image2.Width;.Bottom := Image2.Height;.Canvas.FillRect(rRect);.Right := cWidth;.Bottom := cHeight*5;.Canvas.Brush.Color := clInactiveCaption;.Canvas.FillRect(rRect);.Canvas.Font.Style := [fsBold];i:=0 to 5 do.Canvas.MoveTo(0, i*cHeight);.Canvas.LineTo(cWidth, i*cHeight);;i:= 0 to 1 do.Canvas.MoveTo(i*cWidth,0);.Canvas.LineTo(i*cWidth,cHeight*5 + 1);;.Canvas.TextOut(round(cWidth/2)-2, cHeight + 1, 'X');.Canvas.TextOut(round(cWidth/2)-2, 2*cHeight + 1, 'Y');.Canvas.TextOut(round(cWidth/2)-14, 3*cHeight + 1, 'Связь');.Canvas.TextOut(round(cWidth/2)-14, 4*cHeight + 1, 'Цвет');:= 0;:= TList.Create;:= TList.Create;:= TList.Create;:= TList.Create;;TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;: TShiftState; X, Y: Integer);p: PPnt;, p2: PPnt;:Integer;,mint:Real;

beginfl then:=-1; //переменная расстояния между точками. -1 означает что еще не вычислялась(i_col=1)then //поиск второй точки, максимально близкой к месту нажатия

begini:= 0 to pList.Count-1 do //перебор всех точек:= pList.Items[i]; //данные i-й точки(p^.Linked=false)and(p^.rColor<>PPnt(pList.Items[ip1])^.rColor) //если точка не связана и противоположного цвета тогда:=sqrt(sqr(P^.X - X) + sqr(P^.Y - Y)); //вычисление расстояния

if(minn<0)then //первоночальное присваивание:=i; //запомнить позиции точки из списка

minn:=mint;(mint<minn)then //поиск очередного минимума:=i;:=mint;

end;;(i_col); //переход к друнгомк режиму обработки

PPnt(pList.Items[ip2])^.Linked:=true;

end;(i_col=0)then //поиск первой точки, максимально близкой к месту нажатия

begini:= 0 to pList.Count-1 do //поиск первой точки:= pList.Items[i];(p^.Linked=false):=sqrt(sqr(P^.X - X) + sqr(P^.Y - Y));

if(minn<0)then //первоночальное присваивание

ip1:=i;:=mint;(mint<minn)then:=i;:=mint;;;(i_col);(pList.Items[ip1])^.Linked:=true;;(i_col=2) then //2 точки отобраны?//отрисовка линии:= pList.Items[ip1];:= pList.Items[ip2];:=sum+sqrt(sqr(P1^.X - P2^.X) + sqr(P1^.Y -P2^.Y));.Image1.Canvas.MoveTo(p1^.X, p1^.Y);p1^.rColor = 1 then Form1.Image1.Canvas.Pen.Color := clRed;p1^.rColor = 2 then Form1.Image1.Canvas.Pen.Color := clBlue;.Image1.Canvas.LineTo(round((P1^.X+P2^.X)/2),round((P1^.Y+P2^.Y)/2));p2^.rColor = 1 then Form1.Image1.Canvas.Pen.Color := clRed;p2^.rColor = 2 then Form1.Image1.Canvas.Pen.Color := clBlue;.Image1.Canvas.LineTo(P2^.X,P2^.Y);

//отображение цифр в таблице.Cells[start,1] := IntToStr(P1^.num)+'-'+IntToStr(P2^.num);.Cells[StringGrid1.ColCount-1,1] := IntToStr(round(Sum));(start);_col:=0;;(pList, X,Y);(pList);.Caption := 'Красные точки: ' + IntToStr(redCount);.Caption := 'Синие точки: ' + ' ' + IntToStr(blueCount);redCount = blueCount then Button2.Enabled := true else Button2.Enabled := false;;;TForm1.ToolButton2Click(Sender: TObject);:= 2;.Cursor := crCross;;TForm1.Button1Click(Sender: TObject);i: integer;: PPnt;:= 0;_sh := 0;_1 := Start_sh;_2 := 0;_1 := 0;_2 := 0;(pList);.Canvas.Pen.Color := clBlack;.Canvas.Brush.Color := clWhite;.Canvas.Rectangle(Image1.Canvas.ClipRect);;;TForm1.Button2Click(Sender: TObject);rRect: TRect;: integer;;(pList);;(pList);;TForm1.Button3Click(Sender: TObject);rRect: TRect; Start = pList.Count then //перебор точек по нажатию кнопки "Шаг" завершено

begin.Caption := 'Минимальная сумма отрезков: ' + FloatToStr(minSum);;;:=0;.Clear;

for i:= 0 to pList.Count-1 do //передача всех точек во временный список

begin:= pList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;i:= start to tmpList.Count-2 do //:= tmpList.Items[i];not P^.Linked then:= MaxInt;j := 0 to tmpList.Count - 1 doi<>j then:= tmpList.Items[j];(not P2^.Linked) and (P2^.rColor <> P^.rColor) thensqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y)) < Min then:= sqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y));:= P2;;;;:=Sum+Min;^.Linked := True;^.Linked := True;^.Num := P^.Num;;;i := 0 to start-1 do:= tmpList.Items[i];not P^.Linked then:= MaxInt;j := 0 to tmpList.Count - 1 doi<>j then:= tmpList.Items[j];(not P2^.Linked) and (P2^.rColor <> P^.rColor) thensqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y)) < Min then:= sqrt(sqr(P^.X - P2^.X) + sqr(P^.Y - P2^.Y));:= P2;;;;:=Sum+Min;^.Linked := True;^.Linked := True;^.Num := P^.Num;;;start=0 then:=sum;.Clear;_1 := 0;i:= 0 to tmpList.Count-1 do:= tmpList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;if sum<minsum then:=sum;.Clear;i:= 0 to tmpList.Count-1 do:= tmpList.Items[i];(P);^.X :=Pz.X ;^.Y :=Pz.Y;^.rColor :=Pz.rColor;^.Linked := Pz.Linked;^.Num := Pz.Num;.Add(P);;;_1 := 0;.RowCount := start+2;.ColCount := REdCount+2;i:= 0 to oList.Count-1 do:= oList.Items[i];P^.num <> i+1 then(i_1);.Cells[i_1,start+1]:= IntToStr(i+1) + '-' + IntToStr(p^.num);.Cells[StringGrid1.ColCount-1,start+1] := FloatToStr(round(minSum));.Cells[i_1,0]:= IntToStr(i_1);.Cells[StringGrid1.ColCount-1,0] := 'Сумма';;;.Cells[0,start+1]:= IntToStr(start+1);(oList);.Canvas.FillRect(Image1.Canvas.ClipRect);(oList);(start);;TForm1.N4Click(Sender: TObject);(Handle, 'open','index.chm',nil , Nil, SW_ShowNormal);;TForm1.N3Click(Sender: TObject);.Close;;.


Теги: Задача о красных и синих точках  Курсовая работа (теория)  Информационное обеспечение, программирование
Просмотров: 25030
Найти в Wikkipedia статьи с фразой: Задача о красных и синих точках
Назад