Flying Stars

本文介绍如何使用Dijkstra算法解决求最短路径的问题,包括飞机从起始机场到目标机场的时间计算方法,考虑了时区差异和机场延误等因素。通过不断迭代找到最优路径,并记录每一步的航班信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题是求最短路问题,用dijkstra算法

    初始状态:集合A中只有起始机场,其他机场都在集合B中。

    一直做如下操作:

    飞机从起点飞到D机场(最后一次飞行是从CD)的总时间为:

    若飞机到C的时间 + C机场的延时 <  C-D飞机的起飞时间

        总时间为:到达D的总时间 = 到达D的时间 到达C的时间 + 到达C的总时间

    若飞机到C的时间 + C机场的延时 >  C-D飞机的起飞时间(如果飞机23点到,停留2个小时,而1点钟起飞的飞机就可以赶上)

        总时间为:到达D的总时间 = 到达D的时间 到达C的时间 + 24 * 60 + 到达C的总时间

    找出从集合A中的任一机场到集合B中的任一机场,到达时间最早的班机(即总用时最少的班机),将该班机的目的地机场从B集合移到A集合。

    直到将终点机场放入A集合。

 

    由于题中要求输出飞机的飞行线路(乘坐的班机),所以在每次求出到达时间最早的班机后,不仅将目的地机场从集合B移入集合A时,还要储存下目的地机场的父机场是该航班的起飞机场。最后从终点机场出发,依次找父机场,就可以输出旅行线路了。

 

    为了减少在处理各时区时间上的麻烦,所有飞机的起降时间都换算成格林尼治时间:

    格林尼治时间 = 本地时间 时差

    本地时间 = 格林尼治时间 + 时差

   

为了减少时间进位上的麻烦,题中的所有时间都以分钟为单位,比如:1230起分,储存为750分时起飞。对于所有表示几点钟的时间,要一直维护它在[0,24*60)的范围内。

#include<iostream.h>

#include<string.h>

 

//所有时间是格林尼治时间

//所有时间以分钟为单位

 

struct station{

char sn[6]; //飞机编号

int tag; //目的地

int leave; //起飞时间

int run; //运行时间

} st[110][310]; //储存各个航班的信息

 

char name[110][30]; //地名

char time[10];

int delay[110]; //各机场延时

int timedifference[110]; //各机场时差

int airnum[110]; //各机场航班数

int starttime,namenum,n,m;

bool use[110]; //

int queue[110]; //队中每个机场的编号

int quenum; //队中机场数

int quetime[110]; //队中到每个机场的时间 [0,24*60)

int sumtime[110]; //从起始机场到队中各机场的最短时间

int father[110]; //到队中各机场的前一个机场编号

char quesn[110][6]; //最早到队中各机场的飞机编号

char temsn[110][6]; //没设备那么太大用,把数组的顺序调换一下

 

void main()

{

int i,j,k,p,pt,min,x,y,z;

char place[30];

char c;

 

//超大规模的输入信息:

cin>>name[0]>>name[1];

cin>>time;

starttime=(time[0]-'0')*600+(time[1]-'0')*60+(time[3]-'0')*10+time[4]-'0';

cin>>n;

namenum=2;

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

{

cin>>place;

for (k=0;k<namenum;k++)

if (strcmp(place,name[k])==0)

{

p=k;

break;

}

if (k>=namenum) 

{

p=namenum;

strcpy(name[namenum],place);

namenum++;

}

cin>>c>>time;

if (c=='+')

timedifference[p]=(time[0]-'0')*600+(time[1]-'0')*60+(time[3]-'0')*10+time[4]-'0';

else

timedifference[p]=0-((time[0]-'0')*600+(time[1]-'0')*60+(time[3]-'0')*10+time[4]-'0');

cin>>time;

delay[p]=(time[0]-'0')*600+(time[1]-'0')*60+(time[3]-'0')*10+time[4]-'0';

cin>>m;

airnum[p]=m;

for (j=0;j<m;j++)

{

cin>>st[p][j].sn;

cin>>place;

for (k=0;k<namenum;k++)

if (strcmp(place,name[k])==0)

{

st[p][j].tag=k;

break;

}

if (k>=namenum) 

{

st[p][j].tag=namenum;

strcpy(name[namenum],place);

namenum++;

}

cin>>time;

st[p][j].leave=(time[0]-'0')*600+(time[1]-'0')*60+(time[3]-'0')*10+time[4]-'0';

st[p][j].leave-=timedifference[p]; //换成格林尼治时间

while (st[p][j].leave<0) st[p][j].leave+=24*60; //保证在[0,24*60)范围内

while (st[p][j].leave>=24*60) st[p][j].leave-=24*60;

cin>>time;

st[p][j].run=(time[0]-'0')*600+(time[1]-'0')*60+(time[3]-'0')*10+time[4]-'0';

}

}

//终于输完了!!!  :~(

 

//未加任何变动的dijkstra求最短路算法

quenum=1;

queue[0]=0;

use[0]=true;

quetime[0]=starttime-timedifference[0];

while (quetime[0]<0) quetime[0]+=24*60;

while (quetime[0]>=24*60) quetime[0]-=24*60;

sumtime[0]=0;

father[0]=-1;

while(1)

{

//找从队中机场到非队中机场的最早时间

min=2147483647;

for (i=0;i<quenum;i++)

{

for (j=0;j<airnum[queue[i]];j++)

{

if (use[st[queue[i]][j].tag]==true) continue;

if (quetime[i]+delay[queue[i]]<=st[queue[i]][j].leave)

pt=sumtime[i]+st[queue[i]][j].leave-quetime[i]+st[queue[i]][j].run;

else

pt=sumtime[i]+st[queue[i]][j].leave-quetime[i]+st[queue[i]][j].run+24*60;

if (pt<min)

{

min=pt;

x=queue[i];

y=j;

z=i;

}

}

}

//将该机场放入队中

queue[quenum]=st[x][y].tag;

quetime[quenum]=st[x][y].leave+st[x][y].run;

while (quetime[quenum]<0) quetime[quenum]+=60*24;

while (quetime[quenum]>=24*60) quetime[quenum]-=24*60;

sumtime[quenum]=min;

strcpy(quesn[quenum],st[x][y].sn);

father[quenum]=z;

quenum++;

use[st[x][y].tag]=true;

if (st[x][y].tag==1) break;

}

 

//输出成的d:hh:mm格式(这种方法比较老土)

quenum--;

cout<<sumtime[quenum]/(24*60)<<":";

sumtime[quenum]=sumtime[quenum]%(24*60);

cout<<sumtime[quenum]/600;

sumtime[quenum]=sumtime[quenum]%600;

cout<<sumtime[quenum]/60<<":";

sumtime[quenum]=sumtime[quenum]%60;

cout<<sumtime[quenum]/10;

sumtime[quenum]=sumtime[quenum]%10;

cout<<sumtime[quenum]<<endl;

quetime[quenum]+=timedifference[1];

while (quetime[quenum]<0) quetime[quenum]+=60*24;

while (quetime[quenum]>=24*60) quetime[quenum]-=24*60;

cout<<quetime[quenum]/600;

quetime[quenum]=quetime[quenum]%600;

cout<<quetime[quenum]/60<<":";

quetime[quenum]=quetime[quenum]%60;

cout<<quetime[quenum]/10;

quetime[quenum]=quetime[quenum]%10;

cout<<quetime[quenum]<<endl;

 

//依次输出班机编号

j=0;

for (i=quenum;father[i]!=-1;i=father[i])

{

strcpy(temsn[j],quesn[i]);

j++;

}

for (i=j-1;i>=0;i--)

cout<<temsn[i]<<endl;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值