Интерфейс программного продукта

 

Рисунок 4. Рабочее меню программы

 

 

Рисунок 5. Пользователь рисует на image вершины и рёбра

 

Рисунок 6. Вводим данные в таблицу смежности

 

Рисунок 7. Выполнение задания

3.3 Описание модулей программы

Unit1 – модуль главного окна программы, его код приведен в приложении

Блок-схема основного алгоритма программы

 

 


Замкнутый путь найден?

 

 
 

 

 

 

 


Приложение

 

Код модуля Unit1

 

#include <vcl.h>

#pragma hdrstop

 

#include "Unit1.h"

#include <vector>

#include <math.h>

using namespace std;

 

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

int col = 0;

struct point {

int x, y;

int number;

 

} ;

struct rib{

int x1, x2;

bool k;

};

bool fr = false;

int xr, yr, ir;

vector<point> points;

vector<rib> ribs;

 

TForm1 *Form1;

//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

//Функция для рисования линии со стрелкой

void DrawLine(TCanvas* Canvas, double x0, double y0, double x1, double y1, double ArrowAngle, int ArrowLen){

 

ArrowAngle = ArrowAngle*M_PI/180;

 

//Длина основной линии

int Len = sqrt((x0-x1)*(x0-x1) + (y0-y1)*(y0-y1));

 

//Угол наклона основной линии

double Angle;

if(x0==x1 && y0<y1){

Angle = M_PI/2;

}

else if(x0==x1 && y0>y1){

Angle = 3*M_PI/2;

}

else if(x0>x1 && y0==y1){

Angle = 0;

}

else if(x0<x1 && y0==y1){

Angle = M_PI;

}

 

 

else if(x0>x1 && y0<y1){

Angle = asin((y1-y0)/Len);

}

else if(x0<x1 && y0<y1){

 

Angle = M_PI - asin( (y1-y0)/Len);

}

else if(x0<x1 && y0>y1){

Angle = M_PI-asin((y1-y0)/Len);

}

else if(x0>x1 && y0>y1){

 

Angle = 2*M_PI+asin( (y1-y0)/Len);

}

 

 

int x2 = x1 + ArrowLen * cos(Angle+ArrowAngle); // конец первого лепестка по X

int y2 = y1 - ArrowLen * sin(Angle+ArrowAngle); // конец первого лепестка по Y

 

int x3 = x1 + ArrowLen * cos(Angle-ArrowAngle); // конец второго лепестка по X

int y3 = y1 - ArrowLen * sin(Angle-ArrowAngle); // конец конец второго лепестка по Y

 

// рисуем саму линию

Canvas->MoveTo(x0,y0);

Canvas->LineTo(x1,y1);

 

//Рисуем лепестки

TPoint points[3];

points[0] = Point(x1,y1);

points[1] = Point(x2,y2);

points[2] = Point(x3,y3);

Canvas->Polygon(points, 2);

}

 

 

int res = 0;

void __fastcall TForm1::Image1MouseDown(TObject *Sender,

TMouseButton Button, TShiftState Shift, int X, int Y)

{

if (res==0){

this->Image1->Canvas->Pen->Color=RGB(2, 0, 0);

point el;

el.x = X;

el.y = Y;

el.number = col;

points.push_back(el);

this->Image1->Canvas->Ellipse(X-10, Y-10, X+10, Y+10);

 

this->Image1->Canvas->TextOutA(X+10, Y, IntToStr(col));

this->Image1->Canvas->MoveTo(X, Y);

 

 

this->StringGrid1->RowCount = col+2;

this->StringGrid1->ColCount = col+2;

this->StringGrid1->Cells[col+1][0] = IntToStr(col);

this->StringGrid1->Cells[0][col+1] = IntToStr(col);

 

for (int i=1; i<this->StringGrid1->ColCount; i++){

this->StringGrid1->Cells[i][col+1] = "0";

this->StringGrid1->Cells[col+1][i] = "0";

}

 

col++;

}

if (res==1){//если не используем матрицу смежности

this->Image1->Canvas->Pen->Color=RGB(208, 20, 201);

bool f = false;

for (int i=0; i<col; i++){

int x= point(points[i]).x;

if ((point(points[i]).x>(X-10))&&(point(points[i]).x<(X+10))&&(point(points[i]).y>(Y-10))&&(point(points[i]).y<(Y+10))) {

if (!fr) {f=true; ir =i; fr=true;this->Image1->Canvas->MoveTo(point(points[i]).x, point(points[i]).y);}

else {

DrawLine(this->Image1->Canvas,point(points[ir]).x, point(points[ir]).y,point(points[i]).x, point(points[i]).y, 10,20);

this->StringGrid1->Cells[i+1][ir+1] = "1";

fr=false;

}

}

}

fr=f;

}

 

}

//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn1Click(TObject *Sender)

{

res=0;

}

//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn2Click(TObject *Sender)

{

res=1;

}

//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn3Click(TObject *Sender)

{

 

points.clear();

ribs.clear();

col=0;

Image1->Canvas->FillRect(Image1->Canvas->ClipRect);

this->StringGrid1->ColCount = 1;

this->StringGrid1->RowCount = 1;

this->Memo1->Lines->Clear();

}

//---------------------------------------------------------------------------

 

void __fastcall TForm1::StringGrid1EndDock(TObject *Sender,

TObject *Target, int X, int Y)

{

int k=0;

}

//---------------------------------------------------------------------------

void __fastcall TForm1::StringGrid1SetEditText(TObject *Sender, int ACol,

int ARow, const AnsiString Value)

{

if (!StringGrid1->EditorMode ){

this->Image1->Canvas->Pen->Color=RGB(208, 20, 201);

DrawLine(this->Image1->Canvas,point(points[ARow-1]).x, point(points[ARow-1]).y,point(points[ACol-1]).x, point(points[ACol-1]).y, 10,20);

 

}

 

}

struct el{

int v;

};

//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)

{

int n =this->StringGrid1->ColCount-1; // Количество вершин в графе

float **a;// Матрица смежности графа

a=new float *[n];

for (int i=0; i<n; i++)

a[i]=new float [n];

//инициализация

for (int i=1; i<this->StringGrid1->ColCount; i++){

for (int j=1; j<this->StringGrid1->ColCount; j++){

a[i-1][j-1] = StrToFloat(this->StringGrid1->Cells[j][i]);

}

}

int infinity=10000; // Бесконечность

el * put;

 

put= new el [n];

int sumDl =10000;

int punkt=-1;

 

for (int versh=0; versh<n; versh++){

int sumB = 0;

 

for (int kversh=0; kversh<n; kversh++){

if (kversh!=versh){

 

 

int s=versh;// Номер исходной вершины

int g=kversh; // Номер конечной вершины

int * x; //Массив, содержащий единицы и нули для каждой вершины,

// x[i]=0 - еще не найден кратчайший путь в i-ю вершину,

// x[i]=1 - кратчайший путь в i-ю вершину уже найден

x = new int [n];

int *t; //t[i] - длина кратчайшего пути от вершины s в i

t = new int [n];

el * h; //h[i] - вершина, предшествующая i-й вершине

// на кратчайшем пути

h = new el [n];

//int * tr; //транспорт. 1-жд, 0-шоссе

//tr = new int [n];

// Инициализируем начальные значения массивов

int u; // Счетчик вершин

for (u=0;u<n;u++)

{

t[u]=infinity; //Сначала все кратчайшие пути из s в i

//равны бесконечности

x[u]=0; // и нет кратчайшего пути ни для одной вершины

}

 

int v;

 

h[s].v=0; // s - начало пути, поэтому этой вершине ничего не предшествует

t[s]=0; // Кратчайший путь из s в s равен 0

x[s]=1; // Для вершины s найден кратчайший путь

v=s; // Делаем s текущей вершиной

while(1)

{

// Перебираем все вершины, смежные v, и ищем для них кратчайший путь

for(u=0;u<n;u++)

{

if(a[v][u]==0) continue; // Вершины u и v несмежные

if(x[u]==0 && t[u]>t[v]+a[v][u]) //Если для вершины u еще не

//найден кратчайший путь

// и новый путь в u короче чем

//старый, то

{

t[u]=t[v]+a[v][u]; //запоминаем более короткую длину пути в

//массив t и

h[u].v=v; //запоминаем, что v->u часть кратчайшего

//пути из s->u

}

}

 

// Ищем из всех длин некратчайших путей самый короткий

int w=infinity; // Для поиска самого короткого пути

v=-1; // В конце поиска v - вершина, в которую будет

// найден новый кратчайший путь. Она станет

// текущей вершиной

for(u=0;u<n;u++) // Перебираем все вершины.

{

if(x[u]==0 && t[u]<w) // Если для вершины не найден кратчайший

// путь и если длина пути в вершину u меньше

// уже найденной, то

{

v=u; // текущей вершиной становится u-я вершина

w=t[u];

}

}

if(v==-1)

{

sumB+=infinity;

//Memo1->Lines->Add("Нет пути из вершины ");

break;

}

if(v==g && t[g]<100) // Найден кратчайший путь,

{ // выводим его

 

sumB+= t[g];

 

break;

}

x[v]=1;

}

}

}

if (sumDl>sumB) {

punkt = versh;

sumDl = sumB;

}

}

if (punkt!=-1){

Memo1->Lines->Add("Это пункт "+IntToStr(punkt));

Memo1->Lines->Add("-----Выводим маршруты------");

//теперь высчитывем маршруты до каждого пункта и выводим их

for (int versh=0; versh<n; versh++){

if (punkt!=versh){

 

 

int s=punkt;// Номер исходной вершины

int g=versh; // Номер конечной вершины

int * x; //Массив, содержащий единицы и нули для каждой вершины,

// x[i]=0 - еще не найден кратчайший путь в i-ю вершину,

// x[i]=1 - кратчайший путь в i-ю вершину уже найден

x = new int [n];

int *t; //t[i] - длина кратчайшего пути от вершины s в i

t = new int [n];

el * h; //h[i] - вершина, предшествующая i-й вершине

// на кратчайшем пути

h = new el [n];

// Инициализируем начальные значения массивов

int u; // Счетчик вершин

for (u=0;u<n;u++)

{

t[u]=infinity; //Сначала все кратчайшие пути из s в i

//равны бесконечности

x[u]=0; // и нет кратчайшего пути ни для одной вершины

}

 

int v;

 

h[s].v=0; // s - начало пути, поэтому этой вершине ничего не предшествует

t[s]=0; // Кратчайший путь из s в s равен 0

x[s]=1; // Для вершины s найден кратчайший путь

v=s; // Делаем s текущей вершиной

while(1)

{

// Перебираем все вершины, смежные v, и ищем для них кратчайший путь

for(u=0;u<n;u++)

{

if(a[v][u]==0)continue; // Вершины u и v несмежные

if(x[u]==0 && t[u]>t[v]+a[v][u]) //Если для вершины u еще не

//найден кратчайший путь

// и новый путь в u короче чем

//старый, то

{

t[u]=t[v]+a[v][u]; //запоминаем более короткую длину пути в

//массив t и

h[u].v=v; //запоминаем, что v->u часть кратчайшего

//пути из s->u

}

 

}

 

 

// Ищем из всех длин некратчайших путей самый короткий

int w=infinity; // Для поиска самого короткого пути

v=-1; // В конце поиска v - вершина, в которую будет

// найден новый кратчайший путь. Она станет

// текущей вершиной

for(u=0;u<n;u++) // Перебираем все вершины.

{

if(x[u]==0 && t[u]<w) // Если для вершины не найден кратчайший

// путь и если длина пути в вершину u меньше

// уже найденной, то

{

v=u; // текущей вершиной становится u-я вершина

w=t[u];

}

}

if(v==-1)

{

Memo1->Lines->Add("Нет пути из вершины ");

break;

}

if(v==g) // Найден кратчайший путь,

{ // выводим его

Memo1->Lines->Add("Путь с минимальной величиной из вершины "+IntToStr(s)+" в вершину "+IntToStr(g)+"(в обратном порядке)");

u=g;

this->Image1->Canvas->Pen->Color=RGB(0, 0, 255);

int k=0;

while(u!=s)

{

k++;

this->Memo1->Lines->Add(IntToStr(u));

this->Image1->Canvas->Pen->Color=RGB(208, 158, 20);

 

DrawLine(this->Image1->Canvas,point(points[h[u].v]).x, point(points[h[u].v]).y,point(points[u]).x, point(points[u]).y, 10,20);

u=h[u].v;

}

this->Memo1->Lines->Add(IntToStr(u));

this->Memo1->Lines->Add("Длина пути = "+IntToStr(t[g]));

 

break;

}

x[v]=1;

}

}

}

 

}

else

{

Memo1->Lines->Add("Нет такого пункта. Возможно не все пункты соединены");

}

 

}

//---------------------------------------------------------------------------

 

 

void __fastcall TForm1::Button1Click(TObject *Sender)

{

Image1->Canvas->FillRect(Image1->Canvas->ClipRect);

this->Image1->Canvas->Pen->Color=RGB(2, 0, 0);

for (int i=0;i<col; i++){

int X = point(points[i]).x;

int Y = point(points[i]).y;

this->Image1->Canvas->Ellipse(X-10, Y-10, X+10, Y+10);

 

this->Image1->Canvas->TextOutA(X+10, Y, IntToStr(i));

this->Image1->Canvas->MoveTo(X, Y);

}

this->Image1->Canvas->Pen->Color=RGB(208, 20, 201);

for (int i=1; i<this->StringGrid1->ColCount; i++){

for (int j=1; j<this->StringGrid1->ColCount; j++){

if (this->StringGrid1->Cells[j][i]!="0")

DrawLine(this->Image1->Canvas,point(points[i-1]).x, point(points[i-1]).y,point(points[j-1]).x, point(points[j-1]).y, 10,20);

 

}

}

 

}

//---------------------------------------------------------------------------

 

 

void __fastcall TForm1::Button3Click(TObject *Sender)

{

res=1;

}

//---------------------------------------------------------------------------

 

Заключение

 

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

Можем констатировать, что курсовой проект сделан верно.

 

Список используемой литературы

 

1. Программирование в С++ Builder 6 / А.Я. Архангельский, 2006 г. с. 1304.

2. Программирование. Принципы и практика использования C++ / Бьерн Издательство Вильямс , 2013 г. с. 1248

3. C++ для начинающих. Серия «Шаг за шагом» Г. Шилдт, 2010 г.с. 640 с