unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, StdCtrls,unit2; type TForm1 = class(TForm) StringGrid1: TStringGrid; StringGrid2: TStringGrid; StringGrid3: TStringGrid; StringGrid4: TStringGrid; StringGrid5: TStringGrid; StringGrid6: TStringGrid; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public end; var Form1: TForm1; implementation //реализация класса {$R *.dfm} //////////////////////////////////////////////////////////////////////////////// //процедура проверки при соединении на города //конечный город первого узла должен быть равен //городу отправления второго //////////////////////////////////////////////////////////////////////////////// function test_city(node1:node;node2:node):boolean; begin if node1.city_to=node2.city_from then test_city:=true else test_city:=false; end; //////////////////////////////////////////////////////////////////////////////// //процедура проверки при соединении на отдых //время простоя должно быть больше 4, //но меньше 24 часов //////////////////////////////////////////////////////////////////////////////// function test_time(node1:node;node2:node):boolean; begin if (((node2.time_ot-node1.time_pr)>=4) and ((node2.time_ot-node1.time_pr)<=24)) then test_time:=true else test_time:=false; end; //////////////////////////////////////////////////////////////////////////////// //процедура заполняет массив all_possible_connections нулями и единицами //т.е. она определяет все двойки и тройки узлов, соединение которых вохможно //////////////////////////////////////////////////////////////////////////////// procedure make_all_possible_connections; var i,j,k,key:integer; begin key:=0; i:=1; j:=1; k:=0; //проверяем все двойки while (i<=30) do begin j:=1; while (j<=30) do begin //проверяем возможность соединения if ( //проверка городов на прибытие - отправление test_city(node_arr[i],node_arr[j]) and test_city(node_arr[j],node_arr[i]) and //проверка времени test_time(node_arr[i],node_arr[j]) ) then begin all_possible_connections[i,j,0]:=true; key:=key+1; //счетчик общего кол-ва связей end else all_possible_connections[i,j,0]:=false; inc(j); end; inc(i); end; //проверяем все тройки i:=1;j:=1;k:=1; while (i<=30) do begin j:=1; while (j<=30) do begin k:=1; while (k<=30) do begin //проверяем возможность соединения if ( //проверка городов test_city(node_arr[i],node_arr[j]) and test_city(node_arr[j],node_arr[k]) and test_city(node_arr[k],node_arr[i]) and //проверка времени test_time(node_arr[i],node_arr[j]) and test_time(node_arr[j],node_arr[k]) ) then begin all_possible_connections[i,j,k]:=true; key:=key+1; end else all_possible_connections[i,j,k]:=false; inc(k); //инкремент - увеличение К на 1 end; inc(j); end; inc(i); end; ShowMessage('Количество всевозможных соединений узлов: '+IntToStr(key)); end; //////////////////////////////////////////////////////////////////////////////// //Рекурсивная процедура строит все возможные графы из всех возможных //цепочек узлов. Цепочки упорядочиваются по //первому узлу цепочки. Делается это для того, чтобы в последующем //удалить одинаковые графы. //////////////////////////////////////////////////////////////////////////////// procedure create_graphs(new_graph:graph;new_apc:apc; new_i,new_j,new_k:integer); var i,j,k,w,ret:integer; //////////////////////////////////////////////////////////////////////////////// //функция проверки на соответствие определённой ветви //текущему набору ветвей //основное условие - ни один из узлов ветви не должен встречаться //в предыдущих ветвях графа //////////////////////////////////////////////////////////////////////////////// function test_chain(i,j,k:integer):boolean; var w,w1,s:integer; begin w:=0; s:=length(new_graph)-1; //если длинна графа 0, //т.е. он пустой, значит в нём нет ни одной цепочки //и текущая цепь нам стопроцентно подходит if s=-1 then test_chain:=true; while (w<=s) do begin if (k=0) then begin if ( (new_graph[w][1]<>i) and (new_graph[w][1]<>j) and (new_graph[w][2]<>i) and (new_graph[w][2]<>j) and (new_graph[w][3]<>i) and (new_graph[w][3]<>j) ) then test_chain:=true else test_chain:=false; end else begin if ( (new_graph[w][1]<>i) and (new_graph[w][1]<>j) and (new_graph[w][1]<>k) and (new_graph[w][2]<>i) and (new_graph[w][2]<>j) and (new_graph[w][2]<>k) and (new_graph[w][3]<>i) and (new_graph[w][3]<>j) and (new_graph[w][3]<>k) ) then test_chain:=true else test_chain:=false; end; inc(w); end; end; //////////////////////////////////////////////////////////////////////////////// //функция считает количество элементов всех узлов, входящих в граф //////////////////////////////////////////////////////////////////////////////// function graph_count:integer; var i,j,k:integer; begin i:=0; k:=0; while (i<=(length(new_graph)-1)) do begin inc(k); inc(k); if (new_graph[i][3]<>0) then inc(k); inc(i); end; graph_count:=k; end; //////////////////////////////////////////////////////////////////////////////// //функция сравнивает два графа на идентичность //////////////////////////////////////////////////////////////////////////////// function is_equal(graph1:graph;graph2:graph):boolean; var i,j,key:integer; begin if (length(graph1)<>length(graph2)) then begin is_equal:=false; exit; end; j:=0; //каждую цепочка графа1 сравниваем с каждой цепочкой графа2 key:=0; //и если данные цепочки равны то увеличиваем счетчик одинаковых вхождений на 1 //так как одинаковых цепочек в одном графе быть не может, то если графы равны //(все цепочки графа1 = цепочкам графа2), счетчик одинаковых вхождений в //конечном итоге будет равен коло-ву цепочек графа1 или графа2(их длинна одинаково) while (j<=(length(graph1)-1)) do begin i:=0; // номер цепочки в графе while (i<=(length(graph1)-1)) do begin if ( (graph1[j][1]=graph2[i][1]) and (graph1[j][2]=graph2[i][2]) and (graph1[j][3]=graph2[i][3]) ) then inc(key); //увеличиваем на 1 счетчик одинаковых вхождений inc(i); end; inc(j); end; if key=length(graph1) then is_equal:=true else is_equal:=false; end; begin i:=new_i; //передаем индекс последнего рассмотренног элемента массива APC //проходим весь массив возможных соединений и строим всевозможные графы while (i<=30) do begin j:=new_j; while (j<=30) do begin k:=new_k; while (k<=30) do begin //если элемент массива APC равен 0 //т.е. такое соединение вообще не существует //или уже было рассмотрено //то переходим к следующей цепочке if new_apc[i,j,k]=false then begin inc(k); continue; //запуск следующего витка цикла end; //проверяем текущую цепочку на соотвестствие //(узлы текущей цепочки не должны совпадать с узлами цепочек уже находящихся в данном графе) // всему данному графу //находящемуся в рассмотрении if test_chain(i,j,k) then begin //если цепочка удовлетворяет //то добавляем её в граф //вычёркиваем её из доступных цепочек //и вызываем рекурсивно //для текущей таблицы доступных цепочек //саму функцию create_graph w:=length(new_graph); SetLength(new_graph,w+1); w:=length(new_graph); new_graph[w-1][1]:=i; new_graph[w-1][2]:=j; new_graph[w-1][3]:=k; new_apc[i,j,k]:=false; create_graphs(new_graph,new_apc,i,j,k); end else begin //если же цепочка не удовлетворяет //текущему графу (есть повторения узлов), //то просто вычёркиваем элесент из массива APC(цепочку) из доступных //и вновь рекурсивно вызываем функцию create_graph new_apc[i,j,k]:=false; create_graphs(new_graph,new_apc,i,j,k); end; inc(k); end; inc(j); end; inc(i); end; //когда массив закончился, т.е. мы рассотрели все цепочки //и добавили из них все, котрые удовлетворяли графу //сохраняем наш граф в общий массив всевозможных графов if (not(is_equal(new_graph,old_graph)) and (graph_count=30)) then //сравнение текущего графа //для записи с предыдущим записанным //в массив begin w:=length(all_possible_graphs); setlength(all_possible_graphs,w+1); w:=length(all_possible_graphs); all_possible_graphs[w-1]:=new_graph; old_graph:=new_graph; end; end; procedure TForm1.FormCreate(Sender: TObject); var i:integer; begin //Мехико-акапулько stringgrid1.Cells[0,1]:='a'; stringgrid1.Cells[0,2]:='b'; stringgrid1.Cells[0,3]:='c'; stringgrid1.Cells[0,4]:='d'; stringgrid1.Cells[0,5]:='e'; stringgrid1.Cells[0,0]:='Номер рейса'; stringgrid1.Cells[1,0]:='Отправление'; stringgrid1.Cells[2,0]:='Прибытие'; stringgrid1.Cells[3,0]:='Время в пути'; { stringgrid1.Cells[1,1]:='6'; stringgrid1.Cells[1,2]:='7,5'; stringgrid1.Cells[1,3]:='11,5'; stringgrid1.Cells[1,4]:='19,'; stringgrid1.Cells[1,5]:='24,5'; stringgrid1.Cells[2,1]:='12'; stringgrid1.Cells[2,2]:='13,5'; stringgrid1.Cells[2,3]:='17,5'; stringgrid1.Cells[2,4]:='25'; stringgrid1.Cells[2,5]:='30,5'; } stringgrid1.Cells[1,1]:='4'; stringgrid1.Cells[1,2]:='5'; stringgrid1.Cells[1,3]:='6'; stringgrid1.Cells[1,4]:='7'; stringgrid1.Cells[1,5]:='8'; stringgrid1.Cells[2,1]:='10'; stringgrid1.Cells[2,2]:='11'; stringgrid1.Cells[2,3]:='12'; stringgrid1.Cells[2,4]:='13'; stringgrid1.Cells[2,5]:='14'; stringgrid1.Cells[3,1]:='6'; stringgrid1.Cells[3,2]:='6'; stringgrid1.Cells[3,3]:='6'; stringgrid1.Cells[3,4]:='6'; stringgrid1.Cells[3,5]:='6'; //Акапулько-Мехико stringgrid2.Cells[0,0]:='Номер рейса'; stringgrid2.Cells[1,0]:='Отправление'; stringgrid2.Cells[2,0]:='Прибытие'; stringgrid2.Cells[3,0]:='Время в пути'; stringgrid2.Cells[0,1]:='1'; stringgrid2.Cells[0,2]:='2'; stringgrid2.Cells[0,3]:='3'; stringgrid2.Cells[0,4]:='4'; stringgrid2.Cells[0,5]:='5'; { stringgrid2.Cells[1,1]:='5,5'; stringgrid2.Cells[1,2]:='9'; stringgrid2.Cells[1,3]:='15'; stringgrid2.Cells[1,4]:='18,5'; stringgrid2.Cells[1,5]:='28'; stringgrid2.Cells[2,1]:='11,5'; stringgrid2.Cells[2,2]:='15'; stringgrid2.Cells[2,3]:='21'; stringgrid2.Cells[2,4]:='24,5'; stringgrid2.Cells[2,5]:='34'; } stringgrid2.Cells[1,1]:='5'; stringgrid2.Cells[1,2]:='7'; stringgrid2.Cells[1,3]:='9'; stringgrid2.Cells[1,4]:='11'; stringgrid2.Cells[1,5]:='13'; stringgrid2.Cells[2,1]:='7'; stringgrid2.Cells[2,2]:='9'; stringgrid2.Cells[2,3]:='11'; stringgrid2.Cells[2,4]:='13'; stringgrid2.Cells[2,5]:='15'; stringgrid2.Cells[3,1]:='2'; stringgrid2.Cells[3,2]:='2'; stringgrid2.Cells[3,3]:='2'; stringgrid2.Cells[3,4]:='2'; stringgrid2.Cells[3,5]:='2'; //Мехико-New Мехико stringgrid3.Cells[0,1]:='f'; stringgrid3.Cells[0,2]:='g'; stringgrid3.Cells[0,3]:='h'; stringgrid3.Cells[0,4]:='i'; stringgrid3.Cells[0,5]:='j'; stringgrid3.Cells[0,0]:='Номер рейса'; stringgrid3.Cells[1,0]:='Отправление'; stringgrid3.Cells[2,0]:='Прибытие'; stringgrid3.Cells[3,0]:='Время в пути'; { stringgrid3.Cells[1,1]:='4,5'; stringgrid3.Cells[1,2]:='7'; stringgrid3.Cells[1,3]:='13,5'; stringgrid3.Cells[1,4]:='17'; stringgrid3.Cells[1,5]:='23,5'; stringgrid3.Cells[2,1]:='9,5'; stringgrid3.Cells[2,2]:='12'; stringgrid3.Cells[2,3]:='18,5'; stringgrid3.Cells[2,4]:='22'; stringgrid3.Cells[2,5]:='28,5'; } stringgrid3.Cells[1,1]:='11'; stringgrid3.Cells[1,2]:='13'; stringgrid3.Cells[1,3]:='15'; stringgrid3.Cells[1,4]:='17'; stringgrid3.Cells[1,5]:='19'; stringgrid3.Cells[2,1]:='12'; stringgrid3.Cells[2,2]:='14'; stringgrid3.Cells[2,3]:='16'; stringgrid3.Cells[2,4]:='18'; stringgrid3.Cells[2,5]:='20'; stringgrid3.Cells[3,1]:='1'; stringgrid3.Cells[3,2]:='1'; stringgrid3.Cells[3,3]:='1'; stringgrid3.Cells[3,4]:='1'; stringgrid3.Cells[3,5]:='1'; //New Мехико-Мехико stringgrid4.Cells[0,1]:='6'; stringgrid4.Cells[0,2]:='7'; stringgrid4.Cells[0,3]:='8'; stringgrid4.Cells[0,4]:='9'; stringgrid4.Cells[0,5]:='10'; stringgrid4.Cells[0,0]:='Номер рейса'; stringgrid4.Cells[1,0]:='Отправление'; stringgrid4.Cells[2,0]:='Прибытие'; stringgrid4.Cells[3,0]:='Время в пути'; { stringgrid4.Cells[1,1]:='5'; stringgrid4.Cells[1,2]:='6,5'; stringgrid4.Cells[1,3]:='12'; stringgrid4.Cells[1,4]:='13,5'; stringgrid4.Cells[1,5]:='15'; stringgrid4.Cells[2,1]:='10'; stringgrid4.Cells[2,2]:='11,5'; stringgrid4.Cells[2,3]:='17'; stringgrid4.Cells[2,4]:='18,5'; stringgrid4.Cells[2,5]:='20'; } stringgrid4.Cells[1,1]:='21'; stringgrid4.Cells[1,2]:='22'; stringgrid4.Cells[1,3]:='23'; stringgrid4.Cells[1,4]:='24'; stringgrid4.Cells[1,5]:='25'; stringgrid4.Cells[2,1]:='26'; stringgrid4.Cells[2,2]:='27'; stringgrid4.Cells[2,3]:='28'; stringgrid4.Cells[2,4]:='29'; stringgrid4.Cells[2,5]:='30'; stringgrid4.Cells[3,1]:='5'; stringgrid4.Cells[3,2]:='5'; stringgrid4.Cells[3,3]:='5'; stringgrid4.Cells[3,4]:='5'; stringgrid4.Cells[3,5]:='5'; //Акапулько-New Мехико stringgrid5.Cells[0,1]:='k'; stringgrid5.Cells[0,2]:='l'; stringgrid5.Cells[0,3]:='m'; stringgrid5.Cells[0,4]:='n'; stringgrid5.Cells[0,5]:='o'; stringgrid5.Cells[0,0]:='Номер рейса'; stringgrid5.Cells[1,0]:='Отправление'; stringgrid5.Cells[2,0]:='Прибытие'; stringgrid5.Cells[3,0]:='Время в пути'; { stringgrid5.Cells[1,1]:='5,5'; stringgrid5.Cells[1,2]:='9,5'; stringgrid5.Cells[1,3]:='11'; stringgrid5.Cells[1,4]:='14,5'; stringgrid5.Cells[1,5]:='18,5'; stringgrid5.Cells[2,1]:='12,5'; stringgrid5.Cells[2,2]:='16,5'; stringgrid5.Cells[2,3]:='18'; stringgrid5.Cells[2,4]:='21,5'; stringgrid5.Cells[2,5]:='25,5'; } stringgrid5.Cells[1,1]:='14'; stringgrid5.Cells[1,2]:='15'; stringgrid5.Cells[1,3]:='16'; stringgrid5.Cells[1,4]:='17'; stringgrid5.Cells[1,5]:='18'; stringgrid5.Cells[2,1]:='17'; stringgrid5.Cells[2,2]:='18'; stringgrid5.Cells[2,3]:='19'; stringgrid5.Cells[2,4]:='20'; stringgrid5.Cells[2,5]:='21'; stringgrid5.Cells[3,1]:='3'; stringgrid5.Cells[3,2]:='3'; stringgrid5.Cells[3,3]:='3'; stringgrid5.Cells[3,4]:='3'; stringgrid5.Cells[3,5]:='3'; //New Мехико-Акапулько stringgrid6.Cells[0,1]:='11'; stringgrid6.Cells[0,2]:='12'; stringgrid6.Cells[0,3]:='13'; stringgrid6.Cells[0,4]:='14'; stringgrid6.Cells[0,5]:='15'; stringgrid6.Cells[0,0]:='Номер рейса'; stringgrid6.Cells[1,0]:='Отправление'; stringgrid6.Cells[2,0]:='Прибытие'; stringgrid6.Cells[3,0]:='Время в пути'; { stringgrid6.Cells[1,1]:='6,5'; stringgrid6.Cells[1,2]:='10,5'; stringgrid6.Cells[1,3]:='12'; stringgrid6.Cells[1,4]:='15,5'; stringgrid6.Cells[1,5]:='19,5'; stringgrid6.Cells[2,1]:='13,5'; stringgrid6.Cells[2,2]:='17,5'; stringgrid6.Cells[2,3]:='19'; stringgrid6.Cells[2,4]:='22,5'; stringgrid6.Cells[2,5]:='26,5'; } stringgrid6.Cells[1,1]:='16'; stringgrid6.Cells[1,2]:='18'; stringgrid6.Cells[1,3]:='20'; stringgrid6.Cells[1,4]:='22'; stringgrid6.Cells[1,5]:='24'; stringgrid6.Cells[2,1]:='19'; stringgrid6.Cells[2,2]:='21'; stringgrid6.Cells[2,3]:='23'; stringgrid6.Cells[2,4]:='25'; stringgrid6.Cells[2,5]:='27'; stringgrid6.Cells[3,1]:='3'; stringgrid6.Cells[3,2]:='3'; stringgrid6.Cells[3,3]:='3'; stringgrid6.Cells[3,4]:='3'; stringgrid6.Cells[3,5]:='3'; //записываем данные о рейсах в массив узлов будущего графа for i:=1 to 5 do begin node_arr[i].city_from:='Мехико'; node_arr[i].city_to:='Акапулько'; node_arr[i].time_ot:=StrToFloat(stringgrid1.Cells[1,i]); node_arr[i].time_pr:=StrToFloat(stringgrid1.Cells[2,i]); node_arr[i].name:=stringgrid1.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+5].city_from:='Акапулько'; node_arr[i+5].city_to:='Мехико'; node_arr[i+5].time_ot:=StrToFloat(stringgrid2.Cells[1,i]); node_arr[i+5].time_pr:=StrToFloat(stringgrid2.Cells[2,i]); node_arr[i+5].name:=stringgrid2.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+10].city_from:='Мехико'; node_arr[i+10].city_to:='Нью-Мехико'; node_arr[i+10].time_ot:=StrToFloat(stringgrid3.Cells[1,i]); node_arr[i+10].time_pr:=StrToFloat(stringgrid3.Cells[2,i]); node_arr[i+10].name:=stringgrid3.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+15].city_from:='Нью-Мехико'; node_arr[i+15].city_to:='Мехико'; node_arr[i+15].time_ot:=StrToFloat(stringgrid4.Cells[1,i]); node_arr[i+15].time_pr:=StrToFloat(stringgrid4.Cells[2,i]); node_arr[i+15].name:=stringgrid4.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+20].city_from:='Акапулько'; node_arr[i+20].city_to:='Нью-Мехико'; node_arr[i+20].time_ot:=StrToFloat(stringgrid5.Cells[1,i]); node_arr[i+20].time_pr:=StrToFloat(stringgrid5.Cells[2,i]); node_arr[i+20].name:=stringgrid5.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+25].city_from:='Нью-Мехико'; node_arr[i+25].city_to:='Акапулько'; node_arr[i+25].time_ot:=StrToFloat(stringgrid6.Cells[1,i]); node_arr[i+25].time_pr:=StrToFloat(stringgrid6.Cells[2,i]); node_arr[i+25].name:=stringgrid6.Cells[0,i]; end; end; procedure TForm1.Button1Click(Sender: TObject); //нажатие кнопкм "рассчетать" var graph1:graph; i:integer; begin //записываем данные о рейсах в массив узлов будущего графа for i:=1 to 5 do begin node_arr[i].city_from:='Мехико'; node_arr[i].city_to:='Акапулько'; node_arr[i].time_ot:=StrToFloat(stringgrid1.Cells[1,i]); node_arr[i].time_pr:=StrToFloat(stringgrid1.Cells[2,i]); node_arr[i].name:=stringgrid1.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+5].city_from:='Акапулько'; node_arr[i+5].city_to:='Мехико'; node_arr[i+5].time_ot:=StrToFloat(stringgrid2.Cells[1,i]); node_arr[i+5].time_pr:=StrToFloat(stringgrid2.Cells[2,i]); node_arr[i+5].name:=stringgrid2.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+10].city_from:='Мехико'; node_arr[i+10].city_to:='Нью-Мехико'; node_arr[i+10].time_ot:=StrToFloat(stringgrid3.Cells[1,i]); node_arr[i+10].time_pr:=StrToFloat(stringgrid3.Cells[2,i]); node_arr[i+10].name:=stringgrid3.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+15].city_from:='Нью-Мехико'; node_arr[i+15].city_to:='Мехико'; node_arr[i+15].time_ot:=StrToFloat(stringgrid4.Cells[1,i]); node_arr[i+15].time_pr:=StrToFloat(stringgrid4.Cells[2,i]); node_arr[i+15].name:=stringgrid4.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+20].city_from:='Акапулько'; node_arr[i+20].city_to:='Нью-Мехико'; node_arr[i+20].time_ot:=StrToFloat(stringgrid5.Cells[1,i]); node_arr[i+20].time_pr:=StrToFloat(stringgrid5.Cells[2,i]); node_arr[i+20].name:=stringgrid5.Cells[0,i]; end; for i:=1 to 5 do begin node_arr[i+25].city_from:='Нью-Мехико'; node_arr[i+25].city_to:='Акапулько'; node_arr[i+25].time_ot:=StrToFloat(stringgrid6.Cells[1,i]); node_arr[i+25].time_pr:=StrToFloat(stringgrid6.Cells[2,i]); node_arr[i+25].name:=stringgrid6.Cells[0,i]; end; make_all_possible_connections; //заполнение массива APC setlength(graph1,0); //передаем в функцию create_graphs в качестве параметра old_graph //параметр граф1 длины 0 setlength(all_possible_graphs,0); //установление длины массива APG create_graphs(graph1,all_possible_connections,1,1,0);//заполнение массива APG showmessage('Количество всевозможных графов: '+IntToStr(length(all_possible_graphs))); form2.ShowModal; end; end.