Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
41
Добавлен:
28.06.2014
Размер:
16.19 Кб
Скачать
//---------------------------------------------------------------------------

#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