最便宜航空路线求解.docx

上传人:b****6 文档编号:6747758 上传时间:2023-01-09 格式:DOCX 页数:39 大小:196.50KB
下载 相关 举报
最便宜航空路线求解.docx_第1页
第1页 / 共39页
最便宜航空路线求解.docx_第2页
第2页 / 共39页
最便宜航空路线求解.docx_第3页
第3页 / 共39页
最便宜航空路线求解.docx_第4页
第4页 / 共39页
最便宜航空路线求解.docx_第5页
第5页 / 共39页
点击查看更多>>
下载资源
资源描述

最便宜航空路线求解.docx

《最便宜航空路线求解.docx》由会员分享,可在线阅读,更多相关《最便宜航空路线求解.docx(39页珍藏版)》请在冰豆网上搜索。

最便宜航空路线求解.docx

最便宜航空路线求解

学号:

课程设计

 

题目

最便宜航空线路求解

学院

管理学院

专业

信息管理与信息系统

班级

姓名

指导教师

 

2014

07

03

课程设计任务书

学生:

专业班级:

信管

指导教师:

工作单位:

管理学院

题目:

最便宜航空线路求解

初始条件:

【问题描述】

飞机是远途旅行必不可少的工具,但是高昂的价格也令人颇费思量,因此人们往往宁愿用时间来换金钱而选择较慢的交通工具。

不过,当航班线路变得丰富之后,人们也发现很多时候选择直达航班往往并非最省钱的路径,比如飞往美国选择从国转机就比直飞要便宜多了(虽然这样有坠机的危险)。

这样一来,当采用曲线行进能达到省钱也省时间的目的时,坐飞机还是可以接受的。

为了能够更好地解决路径的选择问题,我们模拟一下通过合适的算法来选出最优航空线路。

参考flight.qunar./上的数据,自选至少10个城市和至少20条航线(不含中转),要求任意两城市间都可达(这并不意味着两个城市之间就一定有直飞航班,比如大陆到),且至少有2条可选飞行路线。

预先定义每条航线的最高定价,航线票价每季度都有折扣机会,但并非必须。

每条线路每季度的折扣率由随机函数产生,围是0.20~1.0(小数点后取两位)。

要求完成的主要任务:

(包括课程设计工作量及其技术要求、说明书撰写等具体要求)

本程序不考虑机场建设费和燃油附加费,只计算机票价格,将其作为路径上的权值处理,耗费矩阵存储结构自行选择。

在真实的情形中,同一线路每天可能有许多航班,也可能每周只有一两趟航班,即便同一天的航班早晚价格也可能有所不同。

为简便计,假定每条线路每天只有一趟航班,不考虑航空公司的差别。

时间安排:

序号

设计容

所用时间

1

问题分析和任务定义

0.5天

2

数据类型和系统设计

0.5天

3

编码实现和静态检查

3天

4

上机准备和上机调试

2天

5

总结和整理设计报告

1天

合计

7天

指导教师签名:

2014年06月25日

系主任(或责任教师)签名:

2014年06月25日

最便宜航空线路求解

1.需求分析

1.1基本要求

(1)所有原始数据一律事先用文本文件保存,读入数据时从文件获取。

(2)航班价格可以用随机函数生成,但建议从网上直接复制真实数据。

(3)可输出所有城市名称以及每一城市所有可直飞到达的城市列表。

(4)可输出任一指定直飞线路(若没有则显示无直飞航班)四个季度的全票和折扣价格。

(5)输入月份、起始城市和目的城市名称,程序能显示出最经济的中转路线选择方案。

1.2输入

(1)从文件read.txt中读取不同城市之间(共10个城市)不同航线(共24条航线)的最高价格输入,四个季度有相同的最高价格。

(2)每条线路每季度的折扣率由随机函数产生,围是0.20~1.00(小数点后取两位),四个季度有不同的折扣。

(3)运行程序时需根据要求从键盘输入相应指令,保证程序的正确运行。

1.3输出

(1)输出所有城市名以及每一城市所有可直飞到达的城市列表(按城市名拼音升序排列):

始发地可直飞目的地

首尔

……

首尔台北

……

(2)输出指定线路四个季度的折扣和全价:

输入:

-台北

输出:

无直飞航班

输入:

-

输出:

季度全票价格折扣折后价格(不计小数,四舍五入)

112406.5806

211927.0834

314754.6679

412308.71070

(3)输入月份、起始城市和目的城市名称,输出最佳方案:

输入:

5-台北

输出:

最佳线路:

-,1503,-台北,791,合计2294

输入:

7-首尔

输出:

最佳线路:

-,880,-首尔,773,合计1653

输入:

10-

输出:

最佳线路:

-,278,合计278

……

1.4测试数据

文本文件read.txt容:

(1)读文本文件read.txt。

若文件名输入正确且文件无错误,则显示主菜单。

若文件名输入错误或文件有错误,则显示“打开输入文件出错”。

(2)根据主菜单提示选择需要执行的功能。

若输入功能序号在0—4之间,则执行相应的功能。

若输入功能序号不在0—4之间,则显示“出错啦!

!

!

请在0-4之间选择!

!

”和主菜单,需重新选择。

(3)选择1,输出城市列表及相应代码。

(4)选择2,输出所有城市名以及每一城市所有可直飞到达的城市列表(按城市名拼音升序排列)。

(5)选择3,先显示城市列表及相应代码,方便后面的输入操作,根据提示“请输入起始城市和目的城市的代码,中间以空格隔开,围(1--10)”输入两个城市代码,若两城市间有直飞航班则显示指定线路四个季度的折扣和全价。

若两城市间无直飞航班则显示“无直飞航班”。

(6)选择4,显示“请输入月份(请在1-12之间选择):

”若月份输入正确,则先显示城市列表及相应代码,方便后面的输入操作,根据提示“请输入起始城市和目的城市的代码,中间以空格隔开,围(1--10)”输入两个城市代码,若代码输入正确,则显示最佳方案。

若月份输入错误,则显示“输入出错”。

若城市代码输入错误,则显示“出错啦!

!

!

”。

(7)选择0,则直接退出程序。

(8)在每一个功能执行完后,都会提示继续执行还是返回主菜单。

 

1.5无向带权费用图

 

2.概要设计

2.1抽象数据类型定义

本程序运用了关于图这种数据结构,它的抽象数据类型定义如下:

typedefstructunDiGraph

{

intnumVerts;//结点

costAdjcost;//邻接矩阵

}unDiGraph,*UNG;

基本操作:

unDiGraph*CreateCostG()

操作结果:

构造带权(费用)图。

PathMat*Floyed(unDiGraph*D)

操作结果:

Floyed函数

求任意两点的最短路径。

 

2.2主程序流程及各程序模块之间的层次(调用)关系

 

 

 

pr(i,0)Floyed()Floyed()

pr(Bcity,0)pr(Bcity,0)

prn_pass(Bcity,Ecity)prn_pass(Bcity,Ecity)

pr(Ecity,0)pr(Ecity,0)

3.详细设计

3.1数据类型

(1)主界面包括

1.查看城市

2.输出所有城市名及所有可直飞到达的城市列表(按城市名拼音升序排列)

3.输入起始城市和目的城市名称,输出指定线路四个季度的折扣和全价

4.输入月份、起始城市和目的城市名称,输出最佳方案

0.退出程序

(2)程序的模块为

#include

#include

#include//需引用的头文件

#defineINF65535//定义一个最大数为无穷值,表示两城市之间无直飞航班

#defineMAX23

typedefintcostAdj[MAX+1][MAX+1];//图邻接矩阵从1开始记数

intPath[MAX+1][MAX+1];//图邻接矩阵从1开始记数

typedefstructunDiGraph

{

intnumVerts;//结点

costAdjcost;//邻接矩阵

}unDiGraph,*UNG;//图的定义

costAdjB,L;

voidpr(inti)//选择城市

voidpri()//输出城市

unDiGraph*CreateCostG()//构造带权(费用)图返回首地址G:

voidFloyed(unDiGraph*D,unDiGraph*M)//Floyed函数求任意两点的最短路径:

voidprn_pass(inti,intj)//为了求从i到j的最短路径,只需要调用如下的过程

voidf_money1()//输出所有城市名及所有可直飞到达的城市列表(按城市名拼音升序排列)

voidf_money2()//输入起始城市和目的城市名称,输出指定线路四个季度的折扣和全价

voidf_money4()//输入月份、起始城市和目的城市名称,输出最佳方案

intLineNumStat(FILE*fp)//统计文本文件的行数

voidmain()//main函数

3.2伪码算法

(1)pr()选择城市

begin

0=>h

Ifj=0thenh=i

Elseifj=1inputadd[i].a

Switch条件选择print城市名

End

(2)pri()输出城市

begin

Print城市代码

1=>i

Whilei<=c_number

{

Printi

调用pr()函数

}

End

(3)unDiGraph*CreateCostF(into)飞机花费的存贮功能

Begin

0=>a,0=>b,1=>h

Wuhan[10],Beijing[10],Xiamen[10],Guangzhou[10],Dalian[10],

Shanghai[10],Changsha[10],Shenzhen[10],Zhengzhou[10],Tianjin[10]

G=(unDiGraph*)malloc(sizeof(unDiGraph)

If!

GthenNULL

1=>i

Whilei

{

Whilej

INF=>G->cost[i][j]初始化使G->cost[i][j]为无穷。

}

c_number=>G->numVerts

while(!

feof(fp))

fscanffp,"%f%f%f%f%f%f%f%f%f%f",&Wuhan[i],&Beijing[i],&Xiamen[i],&Guangzhou[i],&Dalian[i],&Shanghai[i],&Changsha[i],&Shenzhen[i],&Zhengzhou[i],&Tianjin[i]

for(0=>j;j

{

Wuhan[j-1]=>G->cost[j][1]

Beijing[j-1]=>G->cost[j][2]

Xiamen[j-1]=>G->cost[j][3]

Guangzhou[j-1]=>G->cost[j][4]

Dalian[j-1]=>G->cost[j][5]

Shanghai[j-1]=>G->cost[j][6]

Changsha[j-1]=>G->cost[j][7]

Shenzhen[j-1]=>G->cost[j][8]

Zhengzhou[j-1]=>G->cost[j][9]

Tianjin[j-1]=>G->cost[j][10]

}

return(G);

}

End

(4)Floyed(unDiGraph*D,unDiGraph*M)函数Floyed函数求任意两点的最短路径

Begin

c_number=>n

1=>i

while(i<=n)

{

1=>j

while(j<=n)

{

D->cost[i][j]=>A[i][j]初始化矩阵A。

M->cost[i][j]=>C[i][j]

-1=>Path[i][j]初始化矩阵p,置-1.

}

}

for(0=>k;k<=n;k++)为逐步加入的中间结点

{

for(0=>i;i<=n;i++)i为A中行号

{

for(0=>j;j<=n;j++)

if(A[i][k]+A[k][j]

then{A[i][k]+A[k][j]=>A[i][j]

K=>Path[i][j]若i经过k到j比i到j小,则令A[i][j]=A[i][k]+A[k][j]

A[i][j]=>B[i][j]

}

else{

A[i][j]=>B[i][j]

}

}

}

print最短路径为:

End

(5)prn_pass(inti,intj)输出最短路径所经过的点

Begin

If(Path[i][j]!

=-1)

{

递归调用prn_pass(i,Path[i][j])

调用pr(Path[i][j],0)

}

End

(6)f_money1()输出方式1函数

Begin

l

1=>h

do{

Print始发地可直飞目的地

Print

Print天津

Print

Print

Print天津

Print天津

Print天津

Print

Print

Print

Print1.继续输出所有城市名以及每一城市所有可直飞到达的城市列表2.返回主菜单清选择...

inputl输入1或2选择是否继续。

1=>h

}

End

(7)f_money2()输出方式2函数

Begin

1=>h

Bcity,Ecity//起始成市和终点城市

l

money[4]

i,j

s,w

discount[4]

while(h==1)

{

print请输入起始城市和目的城市的代码,中间以空格隔开,围(1--%d,c_number

inputBcity

inputEcity输入起始城市和终点城市的代码。

if(!

((0

=Ecity))

thenprint出错啦!

!

!

exit

(1)

Floyed(CreateTimeF(0),CreateCostF(0))调用Floyed函数。

pr(Bcity,0)显示起始城市。

prn_pass(Bcity,Ecity)调用prn_pass函数,显示最短路径经过的城市。

pr(Ecity,0)显示终点城市。

if(B[Bcity][Ecity]>5000||L[Bcity][Ecity]>10000)

thenprint无直飞航班

else

{Print"季度全票价格折扣折后价格(不计小数,四舍五入)\n"

srand((unsigned)time(NULL))随机种子

for(0=>j;j<4;j++)

{

for(0=>i;i<100;i++)

{

if(!

(i%10))

rand()%80+20=>w

w/100=>s

break;

}

s=>discount[j]

}

for(0=>i;i<4;i++)

{

(floatdiscount[i]*B[Bcity][Ecity]=>money[i]

Print"%d%d%.2lf%.lf\n",i+1,B[Bcity][Ecity],discount[i],money[i]);

Print“打折前的费用是%d元\n",L[Bcity][Ecity]

}

Print1.继续输入起始城市和目的城市名称,输出指定线路四个季度的折扣和全价\n2.返回主菜单\n清选择...

inputl输入1或2选择是否继续。

1=>h

}

End

(8)f_money3()输出方式3函数

Begin

1=>h

Bcity,Ecity起始成市和终点城市

L

money

i,j

s,w

discount[4]

M

month

quarter

do{

Print"请输入月份(请在1-12之间选择):

"

Inputmonth

if(month>=12||month<=1)

{

Print"输入出错!

\n"

exit

(1);

}

pri()输出城市列表及相应代码。

print请输入起始城市和目的城市的代码,中间以空格隔开,围(1--%d,c_number

inputBcity

inputEcity输入起始城市和终点城市的代码。

if(!

((0

=Ecity))

{

Print\n出错啦!

!

!

\n"输入出错

exit

(1)关闭所有文件,终止正在执行的程序

}

Floyed(CreateCostF(0))调用Floyed函数。

if(B[Bcity][Ecity]>5000)

{

print无航班\n"

}

else{

srand((unsigned)time(NULL随机种子

for(0=>j;j<4;j++)

{

for(0=>i;i<100;i++)

{

if(!

(i%10))

rand()%80+20=>w

w/100=>s

break;

}

s=>discount[j]

}

if(1<=month<=3)

{

discount[0]=>m

1=>quarter

Print"你选择的是%d月,位于第%d季度,折扣是%.2lf\n",month,quarter,m

}

elseif(4<=month<=6)

{

discount[1]=>m

2=>quarter

Print"你选择的是%d月,位于第%d季度,折扣是%.2lf\n",month,quarter,m

}

elseif(7<=month<=9)

{

discount[2]=>m

3=>quarter

Print"你选择的是%d月,位于第%d季度,折扣是%.2lf\n",month,quarter,m

}

elseif(10<=month<=12)

{

discount[3]=>m

4=>quarter

Print"你选择的是%d月,位于第%d季度,折扣是%.2lf\n",month,quarter,m

}

(float)m*B[Bcity][Ecity]=>money

Print"最佳线路:

"

pr(Bcity,0)显示起始城市。

prn_pass(Bcity,Ecity)调用prn_pass函数,显示最短路径经过的城市。

pr(Ecity,0)显示终点城市。

Print"合计:

"

Print"%.lf\n",money

}

Print1.继续输入月份、起始城市和目的城市名称,输出最佳方案\n2.返回主菜单\n清选择...

inputl输入1或2选择是否继续。

1=>h

}

End

4.调试分析

4.1问题与解决办法

(1)声明变量语句的位置

我在运行的过程中一直出现这个错误(见下图),系统报错说未定义变量,但我确实定义过了,后来通过在网上XX资料才知道要把声明变量的语句得放到函数的最前面,而printf要放在 所有变量声明语句后面。

修改程序之后,那些错误果然没有了。

(2)文本文件的读取

程序在读取文本文件时总说打开文件出错,原因是read.txt中含有非法字符,删去即可。

而且在程序末尾要记得调用函数fclose(),关闭文件。

(3)把从文本文件读取的数据保存到数组中

编写这一部分的时候总是出现错误,主要是对指向数组的指针认识不清,通过这次编程对它有了更深的了解。

(4)scanf("%s",&add[i].a)和printf("%s",add[i-10].a)

在编写程序阶段,我最开始编写这两个函数的时候是scanf("%c",&add[i].a)printf("%c",add[i-10].a),当时没有看清add[i].a最初的定义,它其实是一个字符数组,所以在运行的时候老出错,后面慢慢研究和调试才知道在输入和输出的格式占位符应该用%s.

(5)随机函数的编写

我以前几乎没接触过随机函数,所以对其不是很了解。

刚开始的时候都不会写,后来在网上找实例,才知道其用法。

而且根据题目的要求产生折扣的围是0.20~1.0(小数点后取两位),所以要产生有小数围的不同随机数,就要用时间作为产生随机数的种子,并且通过取余运算和除以整数100来确定随机数的围。

另外还需引用以下头文件:

#include

#include

4.2算法的时空分析

(1)时间复杂度:

Floyed函数T(n)=O(n2+n3)

(2)空间复杂度:

本程序的空间复杂度均为S(n)=(n2);即存放n2个节点数据辅助空间。

4.3经验和体会

(1)c语言的学习实践很重要。

自学习C语言以来,我们就没怎么练习上机实践能力,所以对于代码的敏感度不够,一个错误出现了,不是很容易发现。

在这次课程设计中,我就犯了很多高手认为很基础的错误,比如说:

printf函数的用法,变量声明的位置,还有就是指针数组的用法。

犯错误是不可避免的,但是我们要认真地去发现错误和修改错误。

我在运行后,知道自己的程序有错误,我首先一步一步慢慢看,慢慢分析,在整个程序中找不出来就将该部分分离出去进行测试,这样,就很容易找到问题所在了。

(2)编写c语言程序必须要细心,特别注意标点符号的书写。

同一个error可能要改个几遍才能改好,由于平时编程经历少的缘故,总感觉有些吃力,要解决这一问题就要自己找题目练习,而不是仅仅依赖于老师每次实验和考试。

另外通过程序的编写还发现自己在c语言编程方面存在不足,要继续加强练习。

(3)要善于利用身边的资源。

资源既包括网络资源也包括人力资源。

遇到一个问题先要通过网络查找解决办法,如果还是不能解决就要学会请教别人,毕竟身边有很多技术牛人和学长学姐,他们都给我很耐心地解答,让我很感动的同时也受益匪浅。

(4)通过这次课设对弗洛伊德算法有了更深刻的了解。

本次课程设计的问题归根到底是求最短路问题,用弗洛伊德算法求任意两点最短路径的过程比用迪杰斯特算法算n次的形式上更加简单,时间复杂度为O(n2+n3),是一个简便的算法。

5.用户使用说明

5.1使用程序的操作步骤

运行程序后输入存储输入数据的文件名,用户会看到程序的主菜单,根据标

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1