数据结构--公交线路的优化查询

在这里插入图片描述
在这里插入图片描述
问题分析:
1.建立合适的图模型
2.根据不同的优化查询调整dij
dij算法的设计思路:
大体思想:
设S是被探查的结点的集合,U是G中除S外的结点集合,初始时,S={s},d(s) =0,若s到U中的结点u有边,则d(u)=边上的权值或长度(具体自己定义),如果没有边,则d(u)=∞
a.从U中选择一个到s距离最小的顶点v,将v加入到S中,此时的距离d(v)就是s到v的最短路径
b.以v为中间结点,重新考虑s到U中的各个结点的距离;如果通过v到U中的结点u的距离比原来不通过v的更小,则更新这个距离值,否则不更新
c.重复a、b直到所有结点都被包含到S中
那么如何去优化?
主要操作是a,b,所以先对a,b两个步骤进行初始的优化:
a:每次选择最短路径,依次遍历o(n),排序操作基本都是o(nlogn),有没有可以降到o(logn),所以可以选择最小堆minheap
b考虑的是s到U中的各个结点,那么想想其实可能得到更新的都是s的邻接点,所以这里可以遍历邻接点。

数据结构的选择:
图的存储:邻接表(边数不多的情况下)
存储节点以及节点与初始点的距离:最小堆
最优路径np_r [1:n] np_v[1:n] //线路号 站点号

数据定义:
//站点

struct site//站点 
{
	char name;
	T x_position;
	T y_position;
}

//线路

struct route//路线 
{   
    int route_num;//线路号  
    int ticket_price;//票价 
    int dep_ti_interval;//发车时间间隔
    int speed;//车速
    int site_num;//站点数
    site<T> *sit;//站点数组
    route()	{}
    void rout()
    {
    	sit=new site<T>[site_num+5];
	}
};

//站点与发车站的距离

struct po//站点
{//记录站点的距离初始站和终点站的距离
	map<int,pair<double,double>>mp;//加快查找速度
}point[100];

//存图链表节点

struct chainNode 
{
        
   int sit_num; //顶点号
   int route_num;//线路号
   double disval;//边距离 
   double timval;//边时间 
   int priceval;//边票价 
   int dep_ti_interval;//发车间隔
   bool index;//标志线路的正反
   chainNode *next;//下一个节点
};

//将信息转化成图的信息//图类(进行加边、求路径)
//邻接表 数组+链表
//插入操作每次插入firstNode,时间复杂度降到o(1)

class chain 
{
   public:
   	  chainNode* firstNode;    
	  int listsize;  
      chain();
      ~chain();
      //存图时插入节点信息
      void insert(int v2,int rout_num,double disv,double timv,int priv,int d_i,bool index);
      int size() {return listsize; }      
};
class linkedGraph
{
	 protected:                  
      chain *aList;   //存图 
	  int np_v[100];//记录前驱节点
	  int np_r[100];//记录点与边所在的线路号
	 public:
	  linkedGraph();
	  ~linkedGraph();
	  //插入边
	  void insertEdge(int v1,int v2,int rout_num,double disv,double timv,int priv,int d_i,double d_h1,double d_h2);
	  //Dijkstra过程
	  void dij(int s,int _dij,int t);
	  void print(int t);
 }    

预处理操作:
预处理数据,进行存图:
1.进行距离的计算,得出disval;
2.进行时间的计算,得出timval;
3.进行线路的正反向判断,并计算正反向的到达时间dep_he;

void init(linkedGraph& li)
{  //<100条线路
    cout<<"请输入线路的个数:"<<endl;
    int num;cin>>num;route<int>rt[100];
	for(int i=1;i<=num;i++)
	{
		cout<<"请输入第"<<i<<"条线路号:"<<endl;cin>>rt[i].route_num;
		cout<<"请输入该条线路站点的个数:"<<endl;cin>>rt[i].site_num;rt[i].rout();
		cout<<"请输入站点名称及位置坐标:(站点名称用大写字母表示,从'A'开始命名)"<<endl; 
		for(int j=0;j<rt[i].site_num;j++)
		{
			cin>>rt[i].sit[j].name;cin>>rt[i].sit[j].x_position;cin>>rt[i].sit[j].y_position;
		}cout<<"请输入发车时间间隔及车速和票价:"<<endl;cin>>rt[i].dep_ti_interval>>rt[i].speed>>rt[i].ticket_price;
	    double dep_he[100];double ddisval[100];double  timval[100];memset(dep_he,0,sizeof(dep_he));memset(ddisval,0,sizeof(ddisval));
	    memset(timval,0,sizeof(timval));
		for(int j=0;j<rt[i].site_num-1;j++)
		{
		    ddisval[j]=sqrt(pow((rt[i].sit[j+1].x_position-rt[i].sit[j].x_position),2)+pow((rt[i].sit[j+1].y_position-rt[i].sit[j].y_position),2));
			timval[j]=ddisval[j]/rt[i].speed;//cout<<rt[i].sit[j].name-'A'<<" "<<timval<<" "<<rt[i].sit[j+1].name-'A'<<endl;
			if(j==0)dep_he[j]=timval[j];else dep_he[j]=dep_he[j-1]+timval[j];
		}point[rt[i].sit[0].name-'A'].mp[rt[i].route_num]=make_pair(0,dep_he[rt[i].site_num-2]);
		for(int j=0;j<rt[i].site_num-1;j++)
		{
			li.insertEdge(rt[i].sit[j].name-'A',rt[i].sit[j+1].name-'A',rt[i].route_num,ddisval[j],timval[j],rt[i].ticket_price,rt[i].dep_ti_interval,dep_he[j],dep_he[rt[i].site_num-2]-dep_he[j]);	
		}	
	 } 
}

//插入或者查找时都选择了空间换时间
dijkstra实现思路:
//:最小堆 邻接点 标记数组
//:最短路径 ,直接跑dij

 if(dis[now->sit_num]>dis[x]+now->disval)
	  {
	 dis[now->sit_num]=dis[x]+now->disval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	 q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num;  
	}	

//:最小时间 (不考虑等车)

if(dis[now->sit_num]>dis[x]+now->timval)
		{
		dis[now->sit_num]=dis[x]+now->timval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	 	q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
		 }

//:最小时间 (考虑等车) 利用结构体struct point 记录 mp[id]=pair<double, double> 然后存点时正向1反向 0区分一下,根据中转站u的下一个点获得1/0,根据u找到point[u].mid[u.route_num].first/point[u].mid[u.route_num].second ,获取该线路车发站到中转站的时间t,然后根据该线路发车间隔dep_ti_interval和到达该站已经经过的时间dis[u],计算需要等待的时间

+画个图举个例子:

松弛操作:
                    if(np_r[x]==now->route_num)//同条线路不需要换乘 
					  {	if(dis[now->sit_num]>dis[x]+now->timval)
					    { 
					  	 	dis[now->sit_num]=dis[x]+now->timval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		    	    q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
					    }
					  } 
					  else//换乘 
					  { double t=0;
					    if(now->index) t=point[x].mp[now->route_num].first;//正向   起点到该点的时间 
						else  t=point[x].mp[now->route_num].second;double timei=0;
				    	if(dis[x]<=t)  timei=t-dis[x];
						else
						{   
							 timei=(now->dep_ti_interval)-((int)(dis[x]-t)%(now->dep_ti_interval)+(dis[x]-t)-(int)(dis[x]-t));
						}
						if(dis[now->sit_num]>dis[x]+timei+now->timval)
	    	         	{
	    		     	dis[now->sit_num]=dis[x]+timei+now->timval;
						pairNode<double>pp;pp.sit_num=now->sit_num;
				     	pp.val=dis[now->sit_num];q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
				        }
					  
					  }

//: 最小花费 因(因为多条线路的票价相同、一个点可以属于多条路线、票价相同的不同路线也得进行计算,同一路线不许计算,
所以根据路线在进行松弛操作时判断线路号是否相同,相同则不加票价,即加0,不同加上对应的票价。
*标记数组flag解决两点之间多条线路问题

                 if(np_r[x]==now->route_num)
	    	       {   
	    	        	if(dis[now->sit_num]>dis[x])
	    	        	{
	    		     	dis[now->sit_num]=dis[x];pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		     	q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
			 	        }	
			    	}
			     	else
			     	{  
			         	if(dis[now->sit_num]>dis[x]+now->priceval)
	    	     	    { 
	    		     	dis[now->sit_num]=dis[x]+now->priceval;
						 pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		     	q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
			         	}	
			    	}

dij完整代码:

void dij(int s,int _dij,int t)
      {  //	output();
	    memset(np_r,0,sizeof(np_r));memset(np_v,0,sizeof(np_v));
      	double dis[100]; minHeap<pairNode<double> >q;bool flag[100];//前去点 线路号记录 
      	while(q.size())q.pop();memset(flag,0,sizeof(flag));
	    for(int i=0;i<100;i++) dis[i]=inf;
	    dis[s]=0;np_v[s]=-1;np_r[s]=-1;pairNode<double>p;p.sit_num=s;p.val=0;q.push(p);
	    while(q.size())
	    {  
	    	int x=q.top().sit_num;q.pop();
	    	if(x==t)break;
	    	if(flag[x])continue;flag[x]=1;
	        for(chainNode *now=aList[x].firstNode;now!=NULL;now=now->next) 
	    	{   
			if(_dij==2)//_dij=1时   最短距离 
	        	{  
	    		   if(dis[now->sit_num]>dis[x]+now->disval)
	    	     	{
	    			dis[now->sit_num]=dis[x]+now->disval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    			q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num;  
			    	}	
		    	}
				else if(_dij==3) //最小时间(不考虑等车) 
				{
					if(dis[now->sit_num]>dis[x]+now->timval)
	    	     	{
	    			dis[now->sit_num]=dis[x]+now->timval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    			q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
				   }
				}
				else if(_dij==4)//等车 最小时间 
				{    
					  if(np_r[x]==now->route_num)//同条线路不需要换乘 
					  {	if(dis[now->sit_num]>dis[x]+now->timval)
					    { 
					  	 	dis[now->sit_num]=dis[x]+now->timval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		    	    q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
					    }
					  } 
					  else//换乘 
					  { double t=0;
					    if(now->index) t=point[x].mp[now->route_num].first;//正向   起点到该点的时间 
						else  t=point[x].mp[now->route_num].second;double timei=0;
				    	if(dis[x]<=t)  timei=t-dis[x];
						else
						{   timei=(now->dep_ti_interval)-((int)(dis[x]-t)%(now->dep_ti_interval)+(dis[x]-t)-(int)(dis[x]-t));
						}
						if(dis[now->sit_num]>dis[x]+timei+now->timval)
	    	         	{
	    		     	dis[now->sit_num]=dis[x]+timei+now->timval;
						pairNode<double>pp;pp.sit_num=now->sit_num;
				     	pp.val=dis[now->sit_num];q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
				        }
					  
					  }
				}	
				else if(_dij==5)//最小花费 
				{   
					if(np_r[x]==now->route_num)
	    	       {   
	    	        	if(dis[now->sit_num]>dis[x])
	    	        	{
	    		     	dis[now->sit_num]=dis[x];pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		     	q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
			 	        }	
			    	}
			     	else
			     	{  
			         	if(dis[now->sit_num]>dis[x]+now->priceval)
	    	     	    { 
	    		     	dis[now->sit_num]=dis[x]+now->priceval;
						 pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		     	q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
			         	}	
			    	}
				}
			
			}
		}  
	  }

递归输出最优路线:

	void print(int t)
    {
     	if(np_v[t]==-1)
     	{char c=t+'A';cout<<c;return;
    	}
    	print(np_v[t]);char c=t+'A';
     	cout<<"--->"<<c<<"(线路"<<np_r[t]<<")";
    }	 

主程序设计:

int main()
{   cout<<"                                        公交线路优化查询"<<endl;
    cout<<"                       -----------------------------------------------------"<<endl;
    cout<<"                       |                                                   |"<<endl;
    cout<<"                       |               主菜单                              |"<<endl;
	cout<<"                       |          1.输入数据(可在过程中增加线路)           |"<<endl;
	cout<<"                       |          2.查询最短距离路径                       |"<<endl;
	cout<<"                       |          3.查询最少时间路径(不考虑等车)         |"<<endl;
	cout<<"                       |          4.查询最少时间路径(考虑等车时间)       |"<<endl;
	cout<<"                       |          5.查询最少花费路径                       |"<<endl;
	cout<<"                       |          6.退出系统                               |"<<endl;
	cout<<"                       -----------------------------------------------------"<<endl; 
	int n;linkedGraph li;cout<<"请输入选择序号(如果是第一步请选择输入数据):"<<endl;freopen("innn.txt","r",stdin);
	while(cin>>n)
	{    
		if(n==6) return 0;
		else if(n==1)init(li);//输入线路信息 
		else 
		{   while(n<1||n>5)
	    	{
			    cout<<"请输入主菜单中的选择序号2-6"<<endl;cin>>n;
			    if(n==6) return 0; if(n>=1&&n<=5)break;
	    	}if(n==1) init(li);
	    	else
	    	{
	    	cout<<"请输入起始站和终点站:"<<endl;char a,b;cin>>a>>b;int s=a-'A';int t=b-'A';
			li.dij(s,n,t);cout<<"查询的结果路线为:";li.print(t);
			}	
		}cout<<endl;
		cout<<"是否还要继续?请输入YES or N0"<<endl;char str[10];cin>>str;
		if(str=="NO") return 0;
		cout<<"请输入选择序号(如果是第一步请选择输入数据):"<<endl;
	
	}
	
}

完整代码:


#include<iostream>
#include<cstring>
#include<cmath>
#include<map>
# define inf 10000
using namespace std;

template<class T>
struct site//站点 
{
	char name;
	T x_position;
	T y_position;
};
template<class T>
struct route//路线 
{   
    int route_num;
    int ticket_price;
    int dep_ti_interval;
    int speed;
    int site_num;
    site<T> *sit;
    route()	{}
    void rout()
    {
    	sit=new site<T>[site_num+5];
	}
};
struct po
{
	map<int,pair<double,double> >mp;//mp[id]=pair<double,double>
}point[100];
struct chainNode 
{
   //顶点号  //线路号  //边距离  //边时间  //边票价 
   int sit_num;
   int route_num;
   double disval;
   double timval;
   int priceval;
   int dep_ti_interval;
   bool index;
   chainNode *next;
   chainNode() {}
   chainNode(int _sit_num,int _route_num,double _disval,double _timval,int _priceval,int de_i,bool _index, chainNode* next)
   :sit_num(_sit_num),route_num(_route_num),disval(_disval),timval(_timval),priceval(_priceval),dep_ti_interval(de_i),index(_index)
    { this->next = next;}
};
class chain 
{
   public:
   	  chainNode* firstNode;    
	  int listsize;  
      chain();
      ~chain();
      void insert(int v2,int rout_num,double disv,double timv,int priv,int d_i,bool index);
      int size()
      {
      	return listsize;
	  }
          
};
chain::chain()
{
   firstNode = NULL;
  listsize=0;
}
chain::~chain()
{
   while (firstNode != NULL)
   {
      chainNode* nextNode = firstNode->next;
      delete firstNode;
      firstNode = nextNode;
   }
}
void chain::insert(int v2,int rout_num,double disv,double timv,int priv,int d_i,bool index)
{   
      firstNode = new chainNode(v2,rout_num,disv,timv,priv,d_i,index,firstNode);listsize++;

}
template<class T>
void changeLength1D(T*& a, int oldLength, int newLength)
{
   if (newLength < 0)
     return;

   T* temp = new T[newLength];            
   int number = min(oldLength, newLength); 
   copy(a, a + number, temp);
   delete [] a;                            
   a = temp;
}
template<class T>
struct pairNode //pairNode<int>pairNode<int> p(val,v)
{
   T val;int sit_num;
   bool operator>(const pairNode& a)
   {
   	return val>a.val;
   }
   bool operator<=(const pairNode&a)
   {
   	 return val<=a.val;
   }
   bool operator<(const pairNode& a)
   {
   	return val<a.val;
   }
   operator=(const pairNode &a)
   {
   	val=a.val;sit_num=a.sit_num;
   }
   
};
template<class T>
class minHeap 
{
   public:
      minHeap(int initialCapacity = 1000);
      ~minHeap() {delete [] heap;}
      bool empty() const {return heapSize == 0;}
      int size() const
          {return heapSize;}
      const T& top()
         {
            return heap[1];
         }
      void pop();
      void push(const T);
      void initialize(T *, int);
      void deactivateArray()
         {heap = NULL; arrayLength = heapSize = 0;}
      void output(ostream& out) const;
   private:
      int heapSize;       // number of elements in queue
      int arrayLength;    // queue capacity + 1
      T *heap;            // element array
};

template<class T>
minHeap<T>::minHeap(int initialCapacity)
{
   arrayLength = initialCapacity + 1;
   heap = new T[arrayLength];
   heapSize = 0;
}

template<class T>
void minHeap<T>::push(const T theElement)
{
   if (heapSize == arrayLength - 1)
   {
      changeLength1D(heap, arrayLength, 2 * arrayLength);
      arrayLength *= 2;
   }
   int currentNode = ++heapSize;
   while (currentNode != 1 && heap[currentNode / 2] > theElement)
   {
      heap[currentNode] = heap[currentNode / 2];
      currentNode /= 2;                          
   }

   heap[currentNode] = theElement;
}

template<class T>
void minHeap<T>::pop()
{
   if (heapSize == 0)   
      return;
   heap[1].~T();
   T lastElement = heap[heapSize--];
   int currentNode = 1,
       child = 2;     
   while (child <= heapSize)
   {
      if (child < heapSize && heap[child] > heap[child + 1])
         child++;
      if (lastElement <= heap[child])
         break;  
      heap[currentNode] = heap[child]; 
      currentNode = child;           
      child *= 2;
   }
   heap[currentNode] = lastElement;
}

template<class T>
void minHeap<T>::initialize(T *theHeap, int theSize)
{
   delete [] heap;
   heap = theHeap;
   heapSize = theSize;
   for (int root = heapSize / 2; root >= 1; root--)
   {
      T rootElement = heap[root];
      int child = 2 * root; 
      while (child <= heapSize)
      {
         if (child < heapSize && heap[child] > heap[child + 1])
            child++;
         if (rootElement <= heap[child])
            break; 
         heap[child / 2] = heap[child]; 
         child *= 2;                  
      }
      heap[child / 2] = rootElement;
   }
}

class linkedGraph
{
	 protected:                  
      chain *aList;   //存图 
	  int np_v[100];
	  int np_r[100];
      
   public:
      linkedGraph()
      {
         aList=new chain[100];
      }
      ~linkedGraph() {delete [] aList;}
	   void insertEdge(int v1,int v2,int rout_num,double disv,double timv,int priv,int d_i,double d_h1,double d_h2)
      {     
            aList[v1].insert(v2,rout_num,disv,timv,priv,d_i,1);//正向 
			aList[v2].insert(v1,rout_num,disv,timv,priv,d_i,0);//反向 
			point[v2].mp[rout_num]=make_pair(d_h1,d_h2);		
      }
    /*  void output()
      {   for(int  i=0;i<=7;i++)
      {
      	  for(chainNode *now=aList[i].firstNode;now!=NULL;now=now->next) 
      	  {
      	  	cout<<now->priceval<<" ";
			}cout<<endl;
	  }
	  }*/
      void dij(int s,int _dij,int t)
      {  //	output();
	    memset(np_r,0,sizeof(np_r));memset(np_v,0,sizeof(np_v));
      	double dis[100]; minHeap<pairNode<double> >q;bool flag[100];//前去点 线路号记录 
      	while(q.size())q.pop();memset(flag,0,sizeof(flag));
	    for(int i=0;i<100;i++) dis[i]=inf;
	    dis[s]=0;np_v[s]=-1;np_r[s]=-1;pairNode<double>p;p.sit_num=s;p.val=0;q.push(p);
	    while(q.size())
	    {  
	    	int x=q.top().sit_num;q.pop();
	    	if(x==t)break;
	    	if(flag[x])continue;flag[x]=1;
	        for(chainNode *now=aList[x].firstNode;now!=NULL;now=now->next) 
	    	{   
			if(_dij==2)//_dij=1时   最短距离 
	        	{  
	    		   if(dis[now->sit_num]>dis[x]+now->disval)
	    	     	{
	    			dis[now->sit_num]=dis[x]+now->disval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    			q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num;  
			    	}	
		    	}
				else if(_dij==3) //最小时间(不考虑等车) 
				{
					if(dis[now->sit_num]>dis[x]+now->timval)
	    	     	{
	    			dis[now->sit_num]=dis[x]+now->timval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    			q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
				   }
				}
				else if(_dij==4)//等车 最小时间 
				{    
					  if(np_r[x]==now->route_num)//同条线路不需要换乘 
					  {	if(dis[now->sit_num]>dis[x]+now->timval)
					    { 
					  	 	dis[now->sit_num]=dis[x]+now->timval;pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		    	    q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
					    }
					  } 
					  else//换乘 
					  { double t=0;
					    if(now->index) t=point[x].mp[now->route_num].first;//正向   起点到该点的时间 
						else  t=point[x].mp[now->route_num].second;double timei=0;
				    	if(dis[x]<=t)  timei=t-dis[x];
						else
						{   timei=(now->dep_ti_interval)-((int)(dis[x]-t)%(now->dep_ti_interval)+(dis[x]-t)-(int)(dis[x]-t));
						}
						if(dis[now->sit_num]>dis[x]+timei+now->timval)
	    	         	{
	    		     	dis[now->sit_num]=dis[x]+timei+now->timval;
						pairNode<double>pp;pp.sit_num=now->sit_num;
				     	pp.val=dis[now->sit_num];q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
				        }
					  
					  }
				}	
				else if(_dij==5)//最小花费 
				{   
					if(np_r[x]==now->route_num)
	    	       {   
	    	        	if(dis[now->sit_num]>dis[x])
	    	        	{
	    		     	dis[now->sit_num]=dis[x];pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		     	q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
			 	        }	
			    	}
			     	else
			     	{  
			         	if(dis[now->sit_num]>dis[x]+now->priceval)
	    	     	    { 
	    		     	dis[now->sit_num]=dis[x]+now->priceval;
						 pairNode<double>pp;pp.sit_num=now->sit_num;pp.val=dis[now->sit_num];
	    		     	q.push(pp);np_v[now->sit_num]=x;np_r[now->sit_num]=now->route_num; 
			         	}	
			    	}
				}
			
			}
		}  
	  }
	void print(int t)
    {
     	if(np_v[t]==-1)
     	{char c=t+'A';cout<<c;return;
    	}
    	print(np_v[t]);char c=t+'A';
     	cout<<"--->"<<c<<"(线路"<<np_r[t]<<")";
    }	 
 };
void init(linkedGraph& li)
{  //<100条线路
    cout<<"请输入线路的个数:"<<endl;
    int num;cin>>num;route<int>rt[100];
	for(int i=1;i<=num;i++)
	{
		cout<<"请输入第"<<i<<"条线路号:"<<endl;cin>>rt[i].route_num;
		cout<<"请输入该条线路站点的个数:"<<endl;cin>>rt[i].site_num;rt[i].rout();
		cout<<"请输入站点名称及位置坐标:(站点名称用大写字母表示,从'A'开始命名)"<<endl; 
		for(int j=0;j<rt[i].site_num;j++)
		{
			cin>>rt[i].sit[j].name;cin>>rt[i].sit[j].x_position;cin>>rt[i].sit[j].y_position;
		}cout<<"请输入发车时间间隔及车速和票价:"<<endl;cin>>rt[i].dep_ti_interval>>rt[i].speed>>rt[i].ticket_price;
	    double dep_he[100];double ddisval[100];double  timval[100];memset(dep_he,0,sizeof(dep_he));memset(ddisval,0,sizeof(ddisval));
	    memset(timval,0,sizeof(timval));
		for(int j=0;j<rt[i].site_num-1;j++)
		{
		    ddisval[j]=sqrt(pow((rt[i].sit[j+1].x_position-rt[i].sit[j].x_position),2)+pow((rt[i].sit[j+1].y_position-rt[i].sit[j].y_position),2));
			timval[j]=ddisval[j]/rt[i].speed;//cout<<rt[i].sit[j].name-'A'<<" "<<timval<<" "<<rt[i].sit[j+1].name-'A'<<endl;
			if(j==0)dep_he[j]=timval[j];else dep_he[j]=dep_he[j-1]+timval[j];
		}point[rt[i].sit[0].name-'A'].mp[rt[i].route_num]=make_pair(0,dep_he[rt[i].site_num-2]);
		for(int j=0;j<rt[i].site_num-1;j++)
		{
			li.insertEdge(rt[i].sit[j].name-'A',rt[i].sit[j+1].name-'A',rt[i].route_num,ddisval[j],timval[j],rt[i].ticket_price,rt[i].dep_ti_interval,dep_he[j],dep_he[rt[i].site_num-2]-dep_he[j]);	
		}	
	 } 
}
int main()
{   cout<<"                                        公交线路优化查询"<<endl;
    cout<<"                       -----------------------------------------------------"<<endl;
    cout<<"                       |                                                   |"<<endl;
    cout<<"                       |               主菜单                              |"<<endl;
	cout<<"                       |          1.输入数据(可在过程中增加线路)           |"<<endl;
	cout<<"                       |          2.查询最短距离路径                       |"<<endl;
	cout<<"                       |          3.查询最少时间路径(不考虑等车)         |"<<endl;
	cout<<"                       |          4.查询最少时间路径(考虑等车时间)       |"<<endl;
	cout<<"                       |          5.查询最少花费路径                       |"<<endl;
	cout<<"                       |          6.退出系统                               |"<<endl;
	cout<<"                       -----------------------------------------------------"<<endl; 
	int n;linkedGraph li;cout<<"请输入选择序号(如果是第一步请选择输入数据):"<<endl;freopen("innn.txt","r",stdin);
	while(cin>>n)
	{    
		if(n==6) return 0;
		else if(n==1)init(li);//输入线路信息 
		else 
		{   while(n<1||n>5)
	    	{
			    cout<<"请输入主菜单中的选择序号2-6"<<endl;cin>>n;
			    if(n==6) return 0; if(n>=1&&n<=5)break;
	    	}if(n==1) init(li);
	    	else
	    	{
	    	cout<<"请输入起始站和终点站:"<<endl;char a,b;cin>>a>>b;int s=a-'A';int t=b-'A';
			li.dij(s,n,t);cout<<"查询的结果路线为:";li.print(t);
			}	
		}cout<<endl;
		cout<<"是否还要继续?请输入YES or N0"<<endl;char str[10];cin>>str;
		if(str=="NO") return 0;
		cout<<"请输入选择序号(如果是第一步请选择输入数据):"<<endl;
	
	}
	
}
  • 10
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值