問題描述
解決方法
1、像第一個問題那就是最短路問題(我代碼采用迪傑斯特拉算法)實現
2、換乘次數最少,那就用bfs廣搜來尋找答案。但是我的代碼不能保證這個最少換乘是最短路程
代碼
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 #include<queue> 6 #include<vector> 7 using namespace std; 8 const int maxn=1e3; 9 const int INF=0x3f3f3f3f; 10 int on[maxn],v[maxn]; 11 //on數組是用來記錄路徑的 12 //v數組是用來記錄最短路徑長度的 13 struct shudui 14 { 15 int x,step; 16 }; 17 struct shudui2 18 { 19 int x,value; 20 }; 21 struct shudui1 22 { 23 int start,value; 24 bool operator < (const shudui1 q)const //這個是用於優先隊列,最短路算法采用”迪傑斯特拉+堆優化“ 25 { 26 return value<q.value; 27 } 28 }; 29 vector<shudui2>w[maxn]; //定義一個shudui2類型的vector容器 30 void bfs(int st,int en) //這個是用bfs找到最少換乘次數 31 { 32 //st代表起點,en代表終點 33 int ans=INF; 34 shudui str1,str2; 35 system("cls"); 36 int flag=0; 37 memset(on,0,sizeof(on)); 38 queue<shudui>r; 39 //為bfs搜索創建一個隊列 40 str1.x=st; 41 str1.step=0; 42 r.push(str1); 43 while(!r.empty()) 44 { 45 str1=r.front();//從隊列頭取元素 46 r.pop(); 47 int x=str1.x; 48 for(int i=0; i<w[x].size(); ++i) //遍歷x這個點能到達的所有點,把它們都加入到隊列中 49 { 50 str2.x=w[x][i].x; 51 on[str2.x]=str1.x; //記錄路徑 52 if(w[x][i].x==en) //這就代表找到了最短路徑 53 { 54 int index=en; 55 flag=1; 56 printf("最短換乘%d次\n",str1.step); 57 printf("以下是路徑\n"); 58 printf("%d",index); 59 while(on[index]>0) //循環打印路徑 60 { 61 index=on[index]; 62 printf("--->%d",index); 63 if(index==st) break; 64 } 65 printf("\n"); 66 break; 67 } 68 69 str2.step=str1.step+1; //每換乘一次要加1 70 r.push(str2); 71 } 72 if(flag) break; 73 } 74 while(!r.empty()) r.pop(); 75 if(!flag) 76 { 77 printf("沒有通向此處航線\n"); 78 } 79 } 80 void JK(int s,int e) //迪傑斯特拉算法求最短路 81 { 82 //s是起點,e是終點 83 system("cls"); 84 memset(on,0,sizeof(on)); 85 memset(v,INF,sizeof(v)); 86 priority_queue<shudui1>r; 87 shudui2 str2; 88 shudui1 str1; 89 v[s]=0; 90 str1.start=s; 91 str1.value=0; 92 r.push(str1); //把起點放入優先隊列 93 while(!r.empty()) 94 { 95 int x,y; 96 str1=r.top(); //從優先隊列頭拿出元素 97 r.pop(); 98 x=str1.start; 99 y=str1.value; 100 if(v[x]<y) continue; 101 //說明在這個點再此之后又入隊了 102 //此次出隊的並不是s到這個點的最短路, 103 //所以在這次更新前點v所連的點已經更過一次了 104 //所以后面也不會進行松弛操作 105 int len=w[x].size(); 106 for(int i=0; i<len; ++i) // 107 { 108 str2=w[x][i]; 109 if((v[x]+str2.value<v[str2.x])) //遍歷x這個點能到達的所有點,把它們都加入到隊列中 110 { 111 on[str2.x]=x; //記錄路徑 112 v[str2.x]=v[x]+str2.value; 113 str1.start=str2.x; 114 str1.value=v[str2.x]; 115 r.push(str1); 116 } 117 } 118 } 119 printf("最短路徑長度為%d\n",v[e]); 120 printf("路徑如下\n"); 121 printf("%d",e); 122 int x=e; 123 while(on[x]>0) //循環打印路徑 124 { 125 x=on[x]; 126 printf("-->%d",x); 127 } 128 printf("\n"); 129 } 130 int main() 131 { 132 int n,m,x; 133 printf("輸入有幾個點,有幾條邊\n"); 134 scanf("%d%d",&n,&m); 135 printf("依次輸入每條路線的起點、終點、距離\n"); 136 while(m--) 137 { 138 shudui2 str2; 139 int x,y,z; 140 scanf("%d%d%d",&x,&y,&z); 141 str2.x=y; 142 str2.value=z; 143 w[x].push_back(str2); //往vector容器里面添加元素 144 str2.x=x; 145 w[y].push_back(str2); 146 } 147 while(1) 148 { 149 int s,e; 150 system("cls"); 151 printf ( " \n"); 152 printf ( " \n"); 153 printf ( " \n"); 154 printf ("-------------------------------------- \n"); 155 printf ("--------------------------------------\n"); 156 printf ("--------丨[0]最短路程 丨---\n"); 157 printf ("--------丨[1]最少換乘 丨---\n"); 158 printf ("--------丨[2]結束 丨---\n"); 159 printf ("----------輸入相應數字----------------\n"); 160 printf ("--------------------------------------- \n"); 161 printf ( " \n"); 162 printf ( " \n"); 163 scanf("%d",&x); //正常if判斷語句 164 if(x==0) 165 { 166 printf("輸入終點編號、起點編號\n"); 167 scanf("%d%d",&s,&e); 168 JK(s,e); 169 } 170 else if(x==1) 171 { 172 printf("輸入終點編號、起點編號\n"); 173 scanf("%d%d",&s,&e); 174 bfs(s,e); 175 } 176 else if(x==2) 177 { 178 break; 179 } 180 else printf("輸入格式不正確\n"); 181 system("pause"); 182 } 183 return 0; 184 } 185 /* 186 測試數據 187 5 5 188 1 2 20 189 2 3 30 190 3 4 20 191 4 5 20 192 1 5 100 193 */