Смекни!
smekni.com

Структуры данных и алгоритмы (стр. 2 из 3)

Way1=record

Way:array [1..4] of way;

next:PWay;

end;

wclass=array [WayClass] of boolean;

PFlight=^Flight;

Flight=record {Информацияорейсе}

company:string[20];

number:string[10];

totalstation:CityCode;

table:DayTable;

path:PWay;

kind:WayKind;

class:WClass;

next:PFlight;

end;

Blank=record {Шаблон для поиска пути}

delay:Week;

BCity,ECity:CityCode;

Kind:array [WayKind] of boolean;

ReBoading:CityCode;

WayTime:Integer;

Cost:Longint;

Class:WClass;

end;

Link=^CityList; {Цепочка рейсов для проезда от начала до конца}

CityList=record {Информация о проезде между двумя пунктами одним рейсом}

DDelay:Word;

waytime:word;

cost:mcost;

Bcity,Target:CityCode;

Flight:PFlight;

Last:Link;

end;

AnswerList=^IAnswer; {Список всех возможных маршрутов следования}

IAnswer=record

path:link;

reboard:citycode;

mincost,maxcost:longint;

waytime:word;

next:AnswerList;

end;

var Lanswer:AnswerList; {глобальная переменная - начало списка маршрутов }

{Добавления нового найденного маршрута}

Procedure Answer(A:Link;cost:longint);

var P,Q:Link; d,s1,s2:word; W,PAnswer:answerlist; r:citycode;

function min(a:mcost):longint; {Минимальная стоимость по классам}

var i:integer; m:longint;

begin

m:=1000000000;

for i:=1 to Mclass do if (m>a[i]) and (a[i]>0) then m:=a[i];

min:=m

end;

function max(a:mcost):longint; {Максимальная стоимость по классам}

var i:integer; m:longint;

begin

m:=a[1];

for i:=2 to Mclass do if m<a[i] then m:=a[i];

max:=m

end;

begin

new(PAnswer);

Panswer^.path:=nil;

P:=A;

s1:=0; s2:=0; {верхняя и нижняя границы цены}

r:=1; {количество пересадок}

d:=0; {время пути}

Repeat

s1:=s1+min(P^.cost); {Подсчет суммы параметров по рейсам в маршруте}

s2:=s2+max(P^.cost);

d:=d+P^.ddelay+P^.waytime;

P:=P^.last; {Переход к следующему рейсу в маршруте}

inc(r);

Until P=nil;

if s1<=cost then begin {Еслисоответствуетцена}

P:=A;

Repeat

new(Q); {Сборкацепочкирейсовмаршрута}

Q^:=P^;

Q^.last:=Panswer^.path;

Panswer^.path:=Q;

P:=P^.last; {Переход к следующему рейсу в маршруте}

Until p=nil;

Panswer^.mincost:=s1; Panswer^.maxcost:=s2; {Сохранениесумарныхценивремени}

Panswer^.waytime:=d; Panswer^.reboard:=r; {ичислапересадоквэлементемаршрута}

W:=LAnswer;

While (W^.next<>nil) and ((W^.next)^.waytime<d) do W:=W^.next; {Поискместавсоответствиивременипути}

While (W^.next<>nil) and ((W^.next)^.reboard<r) and ((W^.next)^.waytime=d) do W:=W^.next; {Поискместапокол-вупересадок}

Panswer^.next:=W^.next; {Добавление маршрута в найденное место}

W^.next:=Panswer;

end

end;

{Возвращает ссылку на информацию об I-ой станции следования}

Function CityInPath(A:Pway; I:citycode):WayP;

var P:Pway;

Begin

P:=A;

While I>4 do begin I:=I-4; P:=P^.next end; {Поиск четверки в которой данная станция}

CityInPath:=@P^.Way[I]; {Результат}

end;

const ReBoadingDelay=120; {Минимальное время пересадки}

{Возвращает время до следещего после указанного времени time отоправление от станции}

{номер N рейса A}

Function DepartureDelay(A:PFlight; N:CityCode; time:week ):word;

var S:word; I:1..4; P:PWay; Q:DayTable;

begin

P:=A^.path;

S:=0;

While N>4 do begin

N:=N-4;

For I:=1 to 4 do S:=S+P^.Way[I].delay+P^.Way[I].reboard; {подсчетвременипутипополнымчетверкам}

P:=P^.next;

end;

For I:=1 to N do S:=S+P^.Way[I].delay+P^.Way[I].reboard; {Подсчетпонеполнойчетверке}

time:=(10080+time-(S mod 10080)) mod 10080; {Время отправления этого рейса от начальной станции}

Q:=A^.Table;

while (Q<>nil) and (Q^.time<time+ReboadingDelay) do Q:=Q^.next; {Поискближайшеговременинатекущейнеделе}

If Q<>nil then Departuredelay:=Q^.time-time else {Еслинатекущейнеделененайден}

DepartureDelay:=10080-time+(A^.Table)^.time; {Поиск ближайщего времени на следующей неделе}

end;

{Поиск всех возможных маршрутов, удовлетворяющих Pattern}

Procedure Search (FlightList:Pflight; const Pattern:Blank; Path:Link);

Var P:Pflight; I,J:CityCode; D,DDelay:Word; K:WayClass; B1,B2:Boolean;

NPattern:Blank; NPath:Link; c:Longint;

{Проверка допустимости маршрута (проверка дублирования города)}

Function Posible (P:Link; L:CityCode):Boolean;

Var b:boolean; i:citycode; Q:pway;

Begin

b:=true;

While (P<>nil) and b do begin {Просмотрвсехпредидущихпересадок}

Q:=P^.flight^.path;

i:=1;

while Q^.way[i].city<>P^.bcity do begin {Поискгородаотправления}

i:=(i mod 4)+1; if i=1 then Q:=Q^.next;

end;

repeat

b:=Q^.way[i].city<>L; {Проверка города на дублирование}

i:=(i mod 4)+1; if i=1 then Q:=Q^.next

until (Q^.way[i].city=P^.target) or not b; {переход к следующему пока не город назначения}

p:=p^.last

end;

Posible:=b;

End;

begin

New(NPath);

NPath^.last:=Path;

P:=FlightList;

While P<>nil do begin {Просмотрвсехрейсов}

if ((Path=nil) or (P<>Path^.Flight)) and Pattern.Kind[P^.Kind] then {неповторяетсярейсисответствуеттипперевозки}

begin

I:=1; {Поиск среди городов следования начальный пункт}

While (I<P^.TotalStation-1) and (CityInPath(P^.path, I)^.city<>Pattern.BCity) do inc (I);

If CityInPath(P^.path, I)^.city=Pattern.BCity then begin {Еслиначальныйнайден}

NPattern:=Pattern; {Подготовка нового шаблона и новой пересадки}

if Npattern.reboading>1 then dec(Npattern.reboading);

Npath^.flight:=P;

For K:=1 to Mclass do Npath^.cost[k]:=0;

Npath^.bcity:=pattern.bcity;

Npath^.Ddelay:=DepartureDelay(P,I,Pattern.delay);

Npath^.waytime:=0;

J:=I;

Repeat {просмотр следующих городов}

Inc(J);

{Внесение исправлений в шаблон и элемент маршрута о цене и времени}

For K:=1 to MClass do If Pattern.Class[K] and P^.class[K] then

Npath^.cost[k]:=Npath^.cost[k]+CityInPath(P^.path,J)^.Cost[K];

Npath^.waytime:=Npath^.waytime+CityInPath(P^.path,J)^.delay;

Npath^.target:=CityInPath(P^.path,J)^.City;

NPattern.Bcity:=CityInPath(P^.path,J)^.City;

Npattern.WayTime:=Pattern.WayTime-Npath^.ddelay-Npath^.waytime;

Npattern.Delay:=(pattern.Delay+Npath^.Ddelay+Npath^.wayTime) mod 10080;

B1:=Posible(Path,CityInPath(P^.path,J)^.City) and (NPattern.WayTime>=0);

{Проверка: не превышены лимиты времени и стоимости и нет повтора пути}

B2:=CityInPath(P^.path,J)^.city=Pattern.ECity; {приехали?}

{Если не приехали и лимиты не превышены то делаем рассмотроим маршруты от текущего до конечного городов}

if B1 and (not B2) and (Pattern.reboading>1) then Search(FlightList,Npattern,Npath);

Npath^.waytime:=Npath^.waytime+CityInPath(P^.path,J)^.reboard;

Until (not B1) or B2 or (J>=P^.totalStation); {Выходим, если есть нарушения или рейс закончился или прехали}

If B2 and B1 then Answer(Npath,pattern.cost); {Если приехали, добавить маршрут в список}

end {найден начальный город}

end; {маршрут подходит по типу}

P:=P^.next; {переход к следущему циклу}

end;

Dispose(NPath)

end;

{Загрузка исходных данных из файла}

Function Load (A:PFlight; FName:String;var City:cities):PFlight;

Var

Source:Text; P:Pflight; I:WayClass; J,MC:CityCode; K:byte;

C:char; Q:Pway; G,L:DayTable; D:string[8];

Begin

Assign(Source,FName);

Reset(Source);

readln(Source,MC); {Количествогородов}

{Считывание название городов и координат на карте }

For J:=1 to MC do begin ReadLn(source,City[j].name); readln(source,city[j].x,city[j].y) end;

While Not EOF(Source) do begin

New(P);

P^.Next:=A;

A:=P;

{Общая информация о рейсе}

ReadLn(Source, P^.company);

ReadLn(Source, P^.number);

ReadLn(Source, P^.kind);

{Стоимость каждого из классов}

For I:=1 to MClass do begin Read(Source,C); P^.class[i]:=C='X' end;

ReadLn(Source, P^.TotalStation);

New(P^.path);

Q:=P^.path;

{информация о городах следования времени пути, стоянках}

For J:=1 to P^.TotalSTation do begin

K:=((J-1) mod 4)+1;

Read(Source,Q^.Way[K].City,Q^.Way[K].Delay,Q^.Way[K].Reboard);

For I:=1 to MClass do If P^.class[I] then Read(Source,Q^.Way[K].cost[I])

else Q^.Way[K].cost[I]:=0;

If (J mod 4)=0 then begin

If (J<>P^.TotalStation) then begin New(Q^.Next); Q:=Q^.next end

else Q^.next:=nil;

end;

ReadLn(Source);

end;

New(P^.Table);

G:=P^.Table;

L:=G;

{Информация о отправлении из начального пункта}

While Not EOLn(Source) do begin

Read(Source,D);

G^.Time:=(ord(D[1])-ord('0')-1)*1440+((ord(D[3])-ord('0'))*10+ord(D[4])-ord('0'))*60

+(ord(D[6])-ord('0'))*10+ord(D[7])-ord('0');

if L^.time>G^.time then write('Wrong data');

If not EOLn(Source) then begin New(G^.next); G:=G^.next end else G^.next:=nil;

end;

ReadLn(Source);

end;

Load:=A;

end;

const line='--------------------------------------------------------------------------------';

procedure graphout(const city:cities);

var

grDriver: Integer;

grMode: Integer;

p:citycode;

begin

grDriver := Detect;

InitGraph(grDriver, grMode,'');

setcolor(12);

outtextxy(200,0,'Карта транспортной схемы');

p:=1;

while (p<maxcity) and (city[p].name<>'') do begin

setcolor(5);

fillellipse(4*city[p].x,380-3*city[p].y,2,2);

setcolor(11);

outtextxy(4*city[p].x+5,376-3*city[p].y,city[p].name);

inc(p)

end;

end;

var List:PFLight; pattern:blank; st:string; p:answerlist;

city:cities; a:dat;

Procedure Input(var Pattern:blank; var a:dat);

var i:citycode; st:string; b:dat; w:real;

begin

with pattern do begin

GotoXY(30,1);

WriteLn('Ввод исходных данных');

write(line);

repeat

write('Начальныйгород ... ');

readln(st);

Bcity:=1; while (BCity<Maxcity) and (City[BCity].name<>st) do inc(BCity);

until BCity<>MaxCity;

repeat

write('Конечный город ... ');

readln(st);

Ecity:=1; while (ECity<Maxcity) and (City[ECity].name<>st) do inc(ECity);

until Ecity<>MaxCity;

repeat

gotoxy(1,5);

WriteLn('Дата отправление:');

DTInput(a);

delay:=a.Dweek*1440+a.time;

Write('Максимальное время пути (сутки):');

readln(w);

waytime:=round(1440*w);

until waytime>0;

write('Максимальная стоимость ... ');

ReadLn(cost);

write('Максимальное число пересадок ... ');

readln(reboading);

write('Тип перевозки (авиа,ж.д.,авто,водн.) ... ');

readln(st);

if st='' then for i:=1 to 4 do kind[i]:=true else

for i:=1 to 4 do kind[i]:=(st[i]='Y') or (st[i]='y') or (st[i]='X') or (st[i]='x');

write('Допустимые классы 123456 ... ');

readln(st);

if st='' then for i:=1 to 4 do class[i]:=true else

for i:=1 to 4 do class[i]:=(st[i]='Y') or (st[i]='y') or (st[i]='X') or (st[i]='x');

end;

end;

procedure outres(p:Answerlist; a:dat);

var k:word; q:link; b:dat; i:citycode; y:pway; c:byte;

begin

k:=0;

while P<>nil do begin

inc(k);

{ write(p^.path^.bcity);}

Q:=P^.path;

b:=a;

while Q<>nil do begin

write(city[q^.bcity].name);

Writeln(' <',q^.flight^.company,q^.Flight^.Number,'> ',city[Q^.Target].name);

newdat(b,Q^.ddelay,b);

write('Отправление: '); writedat(b);

newdat(b,Q^.waytime,b);

write(' Прибытие: '); writedat(b); writeln;

Q:=Q^.last;

end;

newdat(a,p^.waytime,b);

writeln (' цена: ',P^.mincost,' - ',p^.maxcost);

readln(st);

if st='p' then begin

graphout(city);

q:=p^.path;

c:=2;

while q<>nil do begin

i:=1;

y:=q^.flight^.path;

while y^.way[i].city<>q^.bcity do begin

i:=(i mod 4)+1; if i=1 then y:=y^.next;

end;

setcolor(c);

moveto(4*city[q^.bcity].x,380-3*city[q^.bcity].y);

repeat

i:=(i mod 4)+1; if i=1 then y:=y^.next;

lineto(4*city[y^.way[i].city].x,380-3*city[y^.way[i].city].y);

until (y^.way[i].city=q^.target);

Q:=Q^.last; inc(c);

end; repeat until keypressed; CloseGraph;

end;

P:=P^.next;

end;

if k=0 then write('Приданныхусловияхдобратьсянельзя') else writeln('Всего ',k,' маршшрутов');

end;

Begin

List:=Load(nil,'trafic',city);

graphout(city);

repeat until keypressed;

closegraph;

Input(pattern,a);

new(lanswer);

lanswer^.next:=nil;

Search(List,pattern,nil);

outres(Lanswer^.next,a);

end.

Выбор и обоснование набора тестов

В качестве транспортной системы бала взята система, состоящая из 23 городов, соединенных 19 прямыми и таким же числом обратных рейсами. Название городов и перевозчиков вымышленные. Рейсы были разработаны так, что имеется несколько крупных транспортных развязок: PalaceofDream, DiamondWorld, GoldenRiver, SeasideCity; и несколько «удаленных» городов: FarStarCity, OilCity, NorthStarCity.

Разные рейсы отправляются от 3 до 18 раз в неделю.

1. Общий тест

Начальный город ... Tropic Port

Конечный город ... Beatiful

Дата отправление:

Дата ... 8.5.1998 Пт

Время ... 0:0

Максимальное время пути (сутки):3

Максимальная стоимость ... 200

Максимальное число пересадок ... 3

Тип перевозки (авиа,ж.д.,авто,водн.) ...

Допустимыеклассы 123456 ...