Добавил:
Tushkan
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабораторные работы / Захаров / LAB 4 / MainUnit
.cpp//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "MainUnit.h"
#include "OptionsUnit.h"
#include "ResultUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
int Vstart, Vend; // Начальная и конечная вершины искомого минримального пути
int L[1000]; // Номера вершин, формирующих минимальный путь
int Lcount; // Число вершин, формирующих минимальный путь
int Vxy [1000][2]; // Массив координат вершин
int Exy [1000][5]; // Массив координат рёбер (5 строка хранит направление ребра)
int n,m; // Число вершин и рёбер в графе
int MoveV, MoveE; // Перемещаемая вершина и ребро
int XstartDragE, YstartDragE;
AnsiString S[500]; // Строки для формирования отчёта
int Sn; // Число строк в отчёте
int w[1000][1000]; // Матрица весов рёбер графа
int i,j,k,V;
bool fl;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Image1MouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
Norm (X,Y);
if (MoveE>=0)
{
for (i = 0; i < n; i++)
if (Exy[MoveE][0]==Vxy[i][0] && Exy[MoveE][1]==Vxy[i][1])
break;
for (j = 0; j < n; j++)
if (Exy[MoveE][2]==Vxy[j][0] && Exy[MoveE][3]==Vxy[j][1])
break;
for (k = 0; k < m; k++)
{
if (Exy[k][0]==Vxy[i][0] && Exy[k][1]==Vxy[i][1])
{
if (k!=MoveE)
{
Exy[k][0]+=X-XstartDragE;
Exy[k][1]+=Y-YstartDragE;
}
}
else if (Exy[k][2]==Vxy[i][0] && Exy[k][3]==Vxy[i][1])
{
if (k!=MoveE)
{
Exy[k][2]+=X-XstartDragE;
Exy[k][3]+=Y-YstartDragE;
}
}
}
for (k = 0; k < m; k++)
{
if (Exy[k][0]==Vxy[j][0] && Exy[k][1]==Vxy[j][1])
{
if (k!=MoveE)
{
Exy[k][0]+=X-XstartDragE;
Exy[k][1]+=Y-YstartDragE;
}
}
else if (Exy[k][2]==Vxy[j][0] && Exy[k][3]==Vxy[j][1])
{
if (k!=MoveE)
{
Exy[k][2]+=X-XstartDragE;
Exy[k][3]+=Y-YstartDragE;
}
}
}
Vxy[i][0]+=X-XstartDragE;
Vxy[i][1]+=Y-YstartDragE;
Vxy[j][0]+=X-XstartDragE;
Vxy[j][1]+=Y-YstartDragE;
Exy[MoveE][0]+=X-XstartDragE;
Exy[MoveE][1]+=Y-YstartDragE;
Exy[MoveE][2]+=X-XstartDragE;
Exy[MoveE][3]+=Y-YstartDragE;
XstartDragE=X;
YstartDragE=Y;
MoveE=-1;
Image1Paint();
return;
}
if (MoveV>=0)
{
for (i = 0; i < m; i++)
{
if (Exy[i][0]==Vxy[MoveV][0] && Exy[i][1]==Vxy[MoveV][1])
{
Exy[i][0]=X;
Exy[i][1]=Y;
}
else if (Exy[i][2]==Vxy[MoveV][0] && Exy[i][3]==Vxy[MoveV][1])
{
Exy[i][2]=X;
Exy[i][3]=Y;
}
}
Vxy[MoveV][0]=X;
Vxy[MoveV][1]=Y;
MoveV=-1;
}
else if (RadioButton1->Checked)
{
// Блокировка ввода вершин с одинаковыми или близкими координатами
for (i = 0; i < n; i++)
if ((Vxy[i][0]-5)<=X && X<=(Vxy[i][0]+5) && (Vxy[i][1]-5)<=Y && Y<=(Vxy[i][1]+5))
return;
Vxy[n][0]=X;
Vxy[n][1]=Y;
n++;
Button8->Visible=false;
GroupBox1->Visible=false;
}
else
{
for (i = 0; i < n; i++)
if ((Vxy[i][0]-5)<=X && X<=(Vxy[i][0]+5) && (Vxy[i][1]-5)<=Y && Y<=(Vxy[i][1]+5) && Exy[m][0]!=0 && Exy[m][1]!=0)
{
Exy[m][2]=Vxy[i][0];
Exy[m][3]=Vxy[i][1];
// Блокировка ввода петель
if (Exy[m][0]!=Exy[m][2] || Exy[m][1]!=Exy[m][3])
{
m++;
Button8->Visible=false;
GroupBox1->Visible=false;
// Блокирвока ввода парных рёбер
for (j = 0; j < (m-1); j++)
if (Exy[j][0]==Exy[m][0] && Exy[j][1]==Exy[m][1] && Exy[j][2]==Exy[m][2] && Exy[j][3]==Exy[m][3])
m--;
}
}
fl=false;
}
Image1Paint();
}
//---------------------------------------------------------------------------
// Рисование графа
//---------------------------------------------------------------------------
void __fastcall TMainForm::Image1Paint()
{
Image1->Canvas->Brush->Color=OptionsForm->ColorBox1->Selected;
Image1->Canvas->Pen->Color=clBlack;
Image1->Canvas->Rectangle(0,0,500,300);
// Рёбра
Image1->Canvas->Pen->Color=OptionsForm->ColorBox3->Selected;
for (i = 0; i < m; i++)
{
Image1->Canvas->MoveTo(Exy[i][0],Exy[i][1]);
Image1->Canvas->LineTo(Exy[i][2],Exy[i][3]);
}
// Кратчайший путь
if (Button8->Visible)
{
Image1->Canvas->Pen->Color=clRed;
Image1->Canvas->Pen->Width=2;
for (i = 1; i < Lcount; i++)
{
for (j = 0; j < m; j++)
if ((Exy[j][0]==Vxy[L[i-1]][0] && Exy[j][1]==Vxy[L[i-1]][1] && Exy[j][2]==Vxy[L[i]][0] && Exy[j][3]==Vxy[L[i]][1]) ||
(Exy[j][0]==Vxy[L[i]][0] && Exy[j][1]==Vxy[L[i]][1] && Exy[j][2]==Vxy[L[i-1]][0] && Exy[j][3]==Vxy[L[i-1]][1]))
{
Image1->Canvas->MoveTo(Exy[j][0],Exy[j][1]);
Image1->Canvas->LineTo(Exy[j][2],Exy[j][3]);
}
}
Image1->Canvas->Pen->Width=1;
Image1->Canvas->Pen->Color=OptionsForm->ColorBox3->Selected;
}
// Вершины
Image1->Canvas->Brush->Color=OptionsForm->ColorBox2->Selected;
for (i = 0; i < n; i++)
Image1->Canvas->Ellipse(Vxy[i][0]-4,Vxy[i][1]-4,Vxy[i][0]+4,Vxy[i][1]+4);
// Веса рёбер
Image1->Canvas->Brush->Color=OptionsForm->ColorBox1->Selected;
if (OptionsForm->CheckBox2->Checked)
{
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
if (Vxy[j][0]==Exy[i][0] && Vxy[j][1]==Exy[i][1])
break;
for (k = 0; k < n; k++)
if (Vxy[k][0]==Exy[i][2] && Vxy[k][1]==Exy[i][3])
break;
Image1->Canvas->Pen->Color=OptionsForm->ColorBox3->Selected;
Image1->Canvas->Ellipse((Exy[i][0]+Exy[i][2])/2-10,(Exy[i][1]+Exy[i][3])/2-7,(Exy[i][0]+Exy[i][2])/2+7,(Exy[i][1]+Exy[i][3])/2+10);
Image1->Canvas->Font->Color=OptionsForm->ColorBox4->Selected;
Image1->Canvas->TextOutA((Exy[i][0]+Exy[i][2])/2-5,(Exy[i][1]+Exy[i][3])/2-5,IntToStr(((++j)+(++k))%10));
}
}
// Имена вершин
if (OptionsForm->CheckBox1->Checked)
{
Image1->Canvas->Font->Color=OptionsForm->ColorBox4->Selected;
for (i = 0; i < n; i++)
Image1->Canvas->TextOutA(Vxy[i][0]-15,Vxy[i][1]-17,"V"+IntToStr(i+1));
}
// Текущее ребро (в процесс формирования)
if (fl)
{
Image1->Canvas->Pen->Color=OptionsForm->ColorBox3->Selected;
Image1->Canvas->MoveTo(Exy[m][0],Exy[m][1]);
Image1->Canvas->LineTo(Exy[m][2],Exy[m][3]);
}
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Image1MouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
Norm (X,Y);
MoveE=-1;
MoveV=-1;
if (RadioButton1->Checked)
{
for (i = 0; i < n; i++)
{
if ((Vxy[i][0]-5)<=X && X<=(Vxy[i][0]+5) && (Vxy[i][1]-5)<=Y && Y<=(Vxy[i][1]+5))
{
MoveV=i;
return;
}
}
}
else
{
if (RadioButton2->Checked)
Exy[m][4]=0;
else
Exy[m][4]=1;
for (i = 0; i < n; i++)
if ((Vxy[i][0]-5)<=X && X<=(Vxy[i][0]+5) && (Vxy[i][1]-5)<=Y && Y<=(Vxy[i][1]+5))
{
Exy[m][0]=Vxy[i][0];
Exy[m][1]=Vxy[i][1];
fl=true;
return;
}
for (i = 0; i < m; i++)
{
double S1 = Square ((Exy[i][0]-5),(Exy[i][1]-5),(Exy[i][2]-5),(Exy[i][3]-5),X,Y);
double S2 = Square ((Exy[i][0]-5),(Exy[i][1]-5),(Exy[i][0]+5),(Exy[i][1]+5),X,Y);
double S3 = Square ((Exy[i][0]+5),(Exy[i][1]+5),(Exy[i][2]+5),(Exy[i][3]+5),X,Y);
double S4 = Square ((Exy[i][2]-5),(Exy[i][3]-5),(Exy[i][2]+5),(Exy[i][3]+5),X,Y);
double S5 = Square ((Exy[i][0]-5),(Exy[i][1]-5),(Exy[i][0]+5),(Exy[i][1]+5),(Exy[i][2]-5),(Exy[i][3]-5));
double S6 = Square ((Exy[i][0]+5),(Exy[i][1]+5),(Exy[i][2]-5),(Exy[i][3]-5),(Exy[i][2]+5),(Exy[i][3]+5));
if (fabs(S1+S2+S3+S4-S5-S6)<0.001)
{
MoveE=i;
XstartDragE=X;
YstartDragE=Y;
return;
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Image1MouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
if (MoveE>=0)
{
for (i = 0; i < n; i++)
if (Exy[MoveE][0]==Vxy[i][0] && Exy[MoveE][1]==Vxy[i][1])
break;
for (j = 0; j < n; j++)
if (Exy[MoveE][2]==Vxy[j][0] && Exy[MoveE][3]==Vxy[j][1])
break;
for (k = 0; k < m; k++)
{
if (Exy[k][0]==Vxy[i][0] && Exy[k][1]==Vxy[i][1])
{
if (k!=MoveE)
{
Exy[k][0]+=X-XstartDragE;
Exy[k][1]+=Y-YstartDragE;
}
}
else if (Exy[k][2]==Vxy[i][0] && Exy[k][3]==Vxy[i][1])
{
if (k!=MoveE)
{
Exy[k][2]+=X-XstartDragE;
Exy[k][3]+=Y-YstartDragE;
}
}
}
for (k = 0; k < m; k++)
{
if (Exy[k][0]==Vxy[j][0] && Exy[k][1]==Vxy[j][1])
{
if (k!=MoveE)
{
Exy[k][0]+=X-XstartDragE;
Exy[k][1]+=Y-YstartDragE;
}
}
else if (Exy[k][2]==Vxy[j][0] && Exy[k][3]==Vxy[j][1])
{
if (k!=MoveE)
{
Exy[k][2]+=X-XstartDragE;
Exy[k][3]+=Y-YstartDragE;
}
}
}
Vxy[i][0]+=X-XstartDragE;
Vxy[i][1]+=Y-YstartDragE;
Vxy[j][0]+=X-XstartDragE;
Vxy[j][1]+=Y-YstartDragE;
Exy[MoveE][0]+=X-XstartDragE;
Exy[MoveE][1]+=Y-YstartDragE;
Exy[MoveE][2]+=X-XstartDragE;
Exy[MoveE][3]+=Y-YstartDragE;
XstartDragE=X;
YstartDragE=Y;
Image1Paint();
return;
}
if (MoveV>=0)
{
Norm (X,Y);
for (i = 0; i < m; i++)
{
if (Exy[i][0]==Vxy[MoveV][0] && Exy[i][1]==Vxy[MoveV][1])
{
Exy[i][0]=X;
Exy[i][1]=Y;
}
else if (Exy[i][2]==Vxy[MoveV][0] && Exy[i][3]==Vxy[MoveV][1])
{
Exy[i][2]=X;
Exy[i][3]=Y;
}
}
Vxy[MoveV][0]=X;
Vxy[MoveV][1]=Y;
Image1Paint();
}
else if (fl)
{
Norm (X,Y);
Exy[m][2]=X;
Exy[m][3]=Y;
Image1Paint();
}
}
//---------------------------------------------------------------------------
// Кнопки "Удалить рёбра", "Удалить дуги", "Удалить вcё"
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button4Click(TObject *Sender)
{
m=0;
Button8->Visible=false;
GroupBox1->Visible=false;
Image1Paint();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button6Click(TObject *Sender)
{
n=m=0;
Button8->Visible=false;
GroupBox1->Visible=false;
Image1Paint();
}
//---------------------------------------------------------------------------
// Вычисление площади треугольника {(x1,y1),(x2,y2),(x3,y3)}
//---------------------------------------------------------------------------
double TMainForm::Square (int x1, int y1, int x2, int y2, int x3, int y3)
{
double a=sqrt(fabs(pow((x1-x2),2)+pow((y1-y2),2)));
double b=sqrt(fabs(pow((x2-x3),2)+pow((y2-y3),2)));
double c=sqrt(fabs(pow((x1-x3),2)+pow((y1-y3),2)));
return (0.25*sqrt(fabs((a+b+c)*(b+c-a)*(a+c-b)*(a+b-c))));
}
//---------------------------------------------------------------------------
// Нормализация (X,Y)
//---------------------------------------------------------------------------
void TMainForm::Norm (int &x, int &y)
{
if (x>=495) x=495;
if (y>=295) y=295;
if (x<=5) x=5;
if (y<=5) y=5;
}
//---------------------------------------------------------------------------
// Поиск минимального пути и его длины, формирование строк отчёта
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button1Click(TObject *Sender)
{
// Формирование матрицы весов графа
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
w[i][j]=10000; // "Бесконечность"
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
if (Vxy[j][0]==Exy[i][0] && Vxy[j][1]==Exy[i][1])
break;
for (k = 0; k < n; k++)
if (Vxy[k][0]==Exy[i][2] && Vxy[k][1]==Exy[i][3])
break;
w[j][k]=w[k][j]=(j+k+2)%10;
}
// Проверка корректности запроса
if (LabeledEdit1->Text=="" || LabeledEdit2->Text=="" || StrToInt(LabeledEdit1->Text)<=0 || StrToInt(LabeledEdit1->Text)>n || StrToInt(LabeledEdit2->Text)<=0 || StrToInt(LabeledEdit2->Text)>n)
{
MessageDlg ("Введен номер несуществующей вершины!",mtError,TMsgDlgButtons() << mbOK, 0);
return;
}
GroupBox1->Visible=true;
Button8->Visible=true;
Vstart=StrToInt(LabeledEdit1->Text)-1;
Vend=StrToInt(LabeledEdit2->Text)-1;
// Нахождение длины минимального пути
int min;
int Dist[10000];
bool Mark [1000];
S[0]=" Лабораторная работа № 4";
S[1]=" \"Поиск минимального пути\" ";
S[2]="";
S[3]="/";
S[4]="I этап - нахождение длины минимального пути из V"+IntToStr(Vstart+1)+" в V"+IntToStr(Vend+1);
S[5]="";
Sn=6;
for(i=0;i<n; i++)
{
Dist[i]=10000;
Mark[i]=false;
}
V=Vstart;
Mark[V]=true;
Dist[V]=0;
for(;Mark[Vend]==false;)
{
S[Sn++]="V=V"+IntToStr(V+1);
int Sn1=Sn;
S[Sn1]="Г(V"+IntToStr(V+1)+") = {";
Sn++;
for (j=0; j<n;j++)
if(Mark[j]==false)
{
if (Dist[j]>(Dist[V]+w[V][j]))
{
S[Sn1]+=" V"+IntToStr(j+1);
Dist[j]=Dist[V]+w[V][j];
S[Sn++]="l(V"+IntToStr(j+1)+")=l*(V"+IntToStr(V+1)+")+w[V"+IntToStr(V+1)+"][V"+IntToStr(j+1)+"]="+IntToStr(Dist[V]+w[V][j]);
}
}
S[Sn1]+=" }";
min=10000;
for(i=0;i<n;i++)
if(Mark[i]==false && min>Dist[i])
{
min=Dist[i];
V=i;
}
if (min==10000)
{
Label1->Caption="Минимальный путь из вершины V"+IntToStr(Vstart+1)+ " в вершину V"+IntToStr(Vend+1)+" не существует";
return;
}
S[Sn++]="l*(V"+IntToStr(V+1)+")="+IntToStr(Dist[V]);
S[Sn++]="/";
Mark[V]=true;
}
// Построение минимального пути
int G[1000];
int Gn,u;
Lcount=0;
L[Lcount++]=Vend;
S[Sn++]="";
S[Sn++]="II этап - построение пути";
S[Sn++]="/";
for (V=Vend ; L[Lcount-1]!=Vstart ; V=G[u])
{
Gn=0;
S[Sn++]=IntToStr(Lcount)+".";
S[Sn]=" L=[V"+IntToStr(Vend+1);
for (i = 1; i < Lcount; i++)
S[Sn]+=", V"+IntToStr(L[i]+1);
S[Sn++]+="] V = V"+IntToStr(V+1);
for (i = 0; i < n; i++)
{
if (w[V][i]!=-1)
{
G[Gn++]=i;
S[Sn]+="V"+IntToStr(i+1)+" ";
}
}
S[Sn]=" Г(V"+IntToStr(V+1)+")={V"+IntToStr(G[0]+1);
for (i = 1; i < Gn; i++)
S[Sn]+=", V"+IntToStr(G[i]+1);
S[Sn++]+="}";
S[Sn]=" l*(V"+IntToStr(V+1)+")=l*(U)+w(U,V"+IntToStr(V+1)+") => U = V";
for (u = 0; u < Gn; u++)
{
if (Dist[V]==(Dist[G[u]]+w[G[u]][V]))
break;
}
S[Sn++]+=IntToStr(G[u]+1);
S[Sn++]="";
L[Lcount++]=G[u];
}
Label1->Caption="Минимальный путь из вершины V"+IntToStr(Vstart+1)+ " в вершину V"+IntToStr(Vend+1)+":\n V"+IntToStr(L[Lcount-1]+1);
for (i = Lcount-2; i >= 0; i--)
Label1->Caption=Label1->Caption+" -> V"+StrToInt(L[i]+1);
Label1->Caption=Label1->Caption+"\nДлина минимального пути = "+Dist[Vend];
Image1Paint();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button2Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::PageControl1Resize(TObject *Sender)
{
PageControl1->TabWidth=PageControl1->Width/2-2;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button7Click(TObject *Sender)
{
OptionsForm->Show();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button8Click(TObject *Sender)
{
ResultForm->Show();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormShow(TObject *Sender)
{
Image1Paint();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::LabeledEditKeyPress(TObject *Sender, wchar_t &Key)
{
if (!((Key>='0' && Key<='9') || Key==VK_BACK)) Key=0;
}
//---------------------------------------------------------------------------
Соседние файлы в папке LAB 4