实习报告
- 需求分析
- 出于不同目的的旅客对交通工具有不同的要求。例如,因公出差的旅客希望在旅途中的时间尽可能短,出门旅游的旅客则期望旅费尽可能省,而老年旅客则要求中转次数最少。编制一个全国城市间的交通咨询程序,为旅客提供两种或三种最优决策的交通咨询。
2.基本要求
- 提供对城市信息进行编辑(如:添加或删除)的功能。
- 城市之间有两种交通工具:火车和飞机。提供对列车时刻表和飞机航班进行编辑(增设或删除)的功能。
- 提供两种最优决策:最快到达或最省钱到达。全程只考虑一种交通工具。
- 旅途中耗费的总时间应该包括中转站的等候时间。
(5)咨询以用户和计算机的对话方式进行。由用户输入起始站、终点站、最优决策原则和交通工具,输出信息:最快需要多长时间才能到达或者最少需要多少旅费才能到达,并详细说明依次于何时乘坐哪一躺列车或哪一次班机到何地。
3.测试数据
教科书7.6节图7.33的全国交通图。自行设计的列车时刻表和飞机航班。
二、概要设计
为实现上述程序功能,使用链表表示一个多项式。
- 图的抽象数据类型:
ADT graph{
数据对象:邻接表air,train。
操作:
add(e,edge)
操作结果:把一个e加进edge邻接表中。
del(e,edge)
操作结果:把一条边L从edge邻接表中删除。
readfile()
操作结果:从文件中读取时刻表。
shortpath(s,t,edge)
操作结果:使用dijkstra执行最短路的求解。
Printpath(s,t)
操作结果:输出最短路路径。
} - 边的抽象数据类型:
ADT line{
数据对象:起点,终点,编号,起始时间,终止时间,价格。
Print()
操作结果:打印这条边。
}
本程序包含以下模块:
- 主函数模块
int main()
{
初始化;
进入查询系统。
进行各种操作,输出操作结果。
}
(2)图的模块
(3)边的模块
- 详细设计
#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
#define Maxn 500
class graph{
public:
map<string ,int>id;
string place[Maxn];
int tot=0;
struct point{
int num,dis;
int nowtime;
bool operator<(const point &b)const{
return this->dis<b.dis;}
bool operator>(const point &b)const{
return this->dis>b.dis;}
};
struct line{
string Begin,End;
string number;
int st,ed;
int begintime,endtime;
int dis,price;
int change(string s)
{
int res=((s[0]-'0')*10+(s[1]-'0'))*60;
res+=((s[3]-'0')*10+(s[4]-'0'));
return res;
}
line()
{
Begin="";End="";number="";
st=ed=begintime=endtime=price=0;
}
line(string num,string a,string b,string c,string d,int s,int t,int p)
{
number=num;Begin=a;End=b;
begintime=change(c);endtime=change(d);
st=s;ed=t;
price=p;
}
void showtime(int t)
{
printf("%02d:%02d",t/60,t%60);
}
void print()
{
cout<<number<<" "<<Begin<<" "<<End<<" ";
showtime(begintime);cout<<" ";showtime(endtime);cout<<" ";
cout<<price<<endl;
}
};//边的各种信息,构造函数
vector<line>air[Maxn];
vector<line>train[Maxn];
graph()
{
tot=0;
id.clear();
for(int i=0;i<Maxn;i++)air[i].clear();
for(int i=0;i<Maxn;i++)train[i].clear();
}//初始化
int passtime(int x,int y,bool f)
{
if(f)return 0;
x=x%1440;
y=y%1440;
return (y-x+1440)%1440;
}
int length(line k,int type,point intemp,int st,int dis)
{
if(type==1)//求时间最短
{
return passtime(k.begintime,k.endtime,0)+passtime(dis,k.begintime,st==intemp.num);
}
if(type==2)//求花费最短
{
return k.price;
}
if(type==3)//求中转最短
{
return 1;
}
}
void printpath(int st,int v,line path[])
{
if(v==st)return ;
printpath(st,path[v].st,path);
path[v].print();
}//打印路径
void showshow(int Time)
{
int h=Time/60,m=Time%60;
printf("%d小时%d分",h,m);
}//修改时间格式
void shortpath(int st,int ed,vector<line> edge[],int type)
{
bool mark[Maxn];
int dis[Maxn];
line path[Maxn];
const int inf=2000000;
int i,v;
point intemp{st,0,0},newtemp;
for(i=1;i<=tot;i++)
{
mark[i]=false;
dis[i]=inf;
}
dis[st]=0;
priority_queue<point,vector<point>,greater<point> >Q;
Q.push(intemp);
mark[st]=true;
while(!Q.empty())
{
intemp=Q.top();
Q.pop();
mark[intemp.num]=false;
for(v=0;v<edge[intemp.num].size();v++)
{
line k=edge[intemp.num][v];
if(dis[k.ed]>dis[intemp.num]+length(k,type,intemp,st,intemp.nowtime))
{
dis[k.ed]=dis[intemp.num]+length(k,type,intemp,st,intemp.nowtime);
path[k.ed]=k;
if(mark[k.ed]==false)
{
mark[k.ed]=true;
newtemp.nowtime=k.endtime;
newtemp.num=k.ed;
newtemp.dis=dis[k.ed];
Q.push(newtemp);
}
}
}
}
if(dis[ed]==0)
{
printf("\n很抱歉,没有合法的路线!\n\n");
return ;
}
if(type==1)
{
cout<<"\n最少旅行时间为:";showshow(dis[ed]);cout<<endl;
cout<<"选择如下方案:"<<endl;
printpath(st,ed,path);
}
if(type==2)
{
cout<<"\n最少旅费为:"<<dis[ed]<<endl;
cout<<"选择如下方案:"<<endl;
printpath(st,ed,path);
}
if(type==3)
{
cout<<"\n最少中转次数为:"<<dis[ed]-1<<endl;
cout<<"选择如下方案:"<<endl;
printpath(st,ed,path);
}
cout<<endl;
}//dijkstra求最短路,优先队列优化
void add(vector<line> edge[])
{
string number,st,ed;
string sttime,edtime;
int p;
cin>>number>>st>>ed>>sttime>>edtime>>p;
if(id[st]==0)
{
id[st]=++tot;
place[tot]=st;
}
if(id[ed]==0)
{
id[ed]=++tot;
place[tot]=ed;
}
int S=id[st],E=id[ed];
line New(number,st,ed,sttime,edtime,S,E,p);
edge[S].push_back(New);
}//加入一条边
void del(vector<line> edge[])
{
string number,st,ed;
cin>>number>>st>>ed;
vector<line>::iterator It;
It=edge[id[st]].begin();
for(It=edge[id[st]].begin();It!=edge[id[st]].end();It++)
{
if(It->number==number)
{
edge[id[st]].erase(It);
return ;
}
}
}//删除一条边
void solve(string a,string b,int type,string traffic)
{
if(traffic=="火车")
shortpath(id[a],id[b],train,type);
else
shortpath(id[a],id[b],air,type);
}
void readfile()
{
string number,st,ed;
string sttime,edtime;
int p,N;
string kind;
ifstream fin("shuju.txt");
fin>>kind>>N;
for(int i=1;i<=N;i++)
{
fin>>number>>st>>ed>>sttime>>edtime>>p;
if(id[st]==0)
{
id[st]=++tot;
place[tot]=st;
}
if(id[ed]==0)
{
id[ed]=++tot;
place[tot]=ed;
}
int S=id[st],E=id[ed];
line New(number,st,ed,sttime,edtime,S,E,p);
train[S].push_back(New);
}
fin>>kind>>N;
for(int i=1;i<=N;i++)
{
fin>>number>>st>>ed>>sttime>>edtime>>p;
if(id[st]==0)
{
id[st]=++tot;
place[tot]=st;
}
if(id[ed]==0)
{
id[ed]=++tot;
place[tot]=ed;
}
int S=id[st],E=id[ed];
line New(number,st,ed,sttime,edtime,S,E,p);
air[S].push_back(New);
}
}//列车时刻表,航班表
void insertcity(string a)
{
id[a]=++tot;
}
void delcity(string a)
{
train[id[a]].clear();
air[id[a]].clear();
id[a]=0;
}
void print(vector<line> edge[])
{
for(int i=1;i<=tot;i++)
{
for(int j=0;j<edge[i].size();j++)
{
edge[i][j].print();
}
}
cout<<endl;
}
};
int main()
{
graph G;
string oper,op1,op2;
string a,b,x,y,traffic;
string number;
int price;
int type;
while(true)
{
cout<<"全国交通咨询模拟系统"<<endl;
cout<<"输入Q:查询"<<endl;
cout<<"输入E:编辑"<<endl;
cout<<"输入R:导入交通时间表"<<endl;
cout<<"输入PT:输出全部火车班次"<<endl;
cout<<"输入PA:输出全部飞机航班"<<endl;
cin>>oper;
if(oper=="PT")
{
G.print(G.train);
}
if(oper=="PA")
{
G.print(G.air);
}
if(oper=="R")
{
G.readfile();
cout<<"导入成功!"<<endl;
Sleep(800);
system("cls");
}
if(oper=="Q")
{
while(true)
{
cout<<"请依次输入起点站,终点站,最优决策策略(1代表最节约时间,2代表最省钱,3代表中转次数最少),交通方式"<<endl;
cout<<"例子:北京 上海 1 飞机"<<endl;
cout<<"如果想返回上一级菜单请输入Q"<<endl;
cin>>a;
if(a=="Q")break;
cin>>b>>type>>traffic;
G.solve(a,b,type,traffic);
}
}
if(oper=="E")
{
while(true)
{
// cout<<"输入R:从data.txt中读取时刻表信息"<<endl;
cout<<"输入IC:手动增加一个城市"<<endl;
cout<<"输入DC:手动删除一个城市"<<endl;
cout<<"输入T:手动编辑火车交通信息"<<endl;
cout<<"输入A:手动编辑飞机交通信息"<<endl;
cout<<"输入Q:返回上一层"<<endl;
cin>>op1;
if(op1=="R")
{
G.readfile();
}
if(op1=="IC")
{
cout<<"输入增加的城市名字:";
cin>>a;
G.insertcity(a);
cout<<endl;
}
if(op1=="DC")
{
cout<<"输入删除的城市名字:";
cin>>a;
G.delcity(a);
cout<<endl;
}
if(op1=="T")
{
cout<<"输入I:增加一条路线。"<<endl;
cout<<"输入D:删除一条路线。"<<endl;
cin>>op2;
if(op2=="I")
{
cout<<"按照车次号,起始站,终点站,发车时间,到达时间,价格输入"<<endl;
cout<<"例子:K71 重庆 上海 06:02 18:11 493"<<endl;
//cin>>number>>a>b>>x>>y>>price;
G.add(G.train);
cout<<endl;
}
else
{
cout<<"输入车次号,起始站,终点站"<<endl;
cout<<"例子:K71 重庆 上海"<<endl;
G.del(G.train);
cout<<endl;
}
}
if(op1=="A")
{
cout<<"输入I:增加一条路线。"<<endl;
cout<<"输入D:删除一条路线。"<<endl;
cin>>op2;
if(op2=="I")
{
cout<<"按照航班,起始站,终点站,起飞时间,到达时间,价格输入"<<endl;
cout<<"例子:A73 重庆 上海 06:02 10:11 1493"<<endl;
G.add(G.air);
cout<<endl;
}
else
{
cout<<"输入航班号,起始站,终点站"<<endl;
cout<<"例子:A73 重庆 上海"<<endl;
G.del(G.air);
cout<<endl;
}
}
if(op1=="Q")
{
system("cls");
break;
}
}
}
}
return 0;
}
/*
学号 姓名 周三
*/ - 调试分析
- 一开始算法有些问题,经过数据调试之后改正确了。
- 算法的时空分析
- 时间复杂度:使用邻接链表处理数据,使用Dijkstra算法,复杂度O(n^2)。
- 空间复杂度:用邻接链表vector存储了每一条边,复杂度O(m)。
- 调试验收
写的代码基本没问题,一次验收通过,各个模块都运行正常。
六、用户手册
1.本程序的运行环境为DOS操作系统,执行文件为:多项式.exe
2.进入程序后显示引导页面:
顺序输入即可。
七、测试结果
测试样例:北京到上海的最节约时间的交通方案。
如图输出结果。
- 附录
main.cpp //主程序